見出し画像

C#でレイキャストを使うには?

 ゲーム開発ツール"RPG Developer Bakin"C#プラグイン開発に関する情報を記します。
 今回のお題は「レイキャスト」です。





1. サンプルコード

 以下に、レイキャストがヒットした対象との距離を測定するメソッドのサンプルコードを記します。

// レイキャストでヒットした対象との距離を測定するメソッド
// chrはレイキャスト発射元のキャストイベント
// fromはレイキャストの発射位置座標
// toはレイキャストが向かう地点の座標
// maxDistanceはレイキャスト距離
public float Raycast_GetAllObjectDistance(MapCharacter chr, Vector3 from, Vector3 to, float maxDistance)
{

     to = Vector3.Add(from, Vector3.Multiply(Vector3.Normalize(Vector3.Subtract(to, from) ), maxDistance) );
     //fromからtoまでの正規化ベクトルにmaxDistanceを乗算してレイキャスト距離を設定しtoに上書き
            
     var hit = new SharpKmyPhysics.RayCastHit(); //hitはレイキャストがヒットした対象の情報を格納する変数

     var result = chr.getRigidbody().getPhysicsBase().rayCast(Util.ToKmyVector(from), Util.ToKmyVector(to), (ushort)CollisionType.ALL, hit);
     // resultはレイキャストがヒットした場合にtrueとなる
     // chrは発射元のキャストイベント
     // Util.ToKmyVector()はMicrosoft.Xna.Framework.Vector3型をBakin専用のSharpKmyMath.Vector3型に変換するもの
     // (ushort)CollisionType.ALLはレイキャストがヒットするコリジョンの種類を全種類(ALL)に設定している

     if(result)
     {
          return hit.distance; //hit.distanceでレイキャストがヒットした対象との距離を取得できる
     } else {
          return -1; //レイキャストがヒットしない場合は-1を返す
     }

}

2. 捕捉説明

2.1 使用例

 例として、上記のRaycast_GetAllObjectDistanceメソッドを使用して、プレイヤーからある地点へレイキャストを発射する場合は次のように記述します。

using Microsoft.Xna.Framework; //Vector3型を使用するために冒頭で記述
var from = mapScene.hero.getPosition(); //プレイヤーの座標を取得
from.Y += mapScene.hero.collisionStatus.GetHeight() * 0.5f;
//デフォルトでは足元が発射地点となっておりうまく動作しないためプレイヤー当たり判定の半分の高さまで発射地点を持ち上げる
//ちなみにcollisionStatus.GetHeight()でイベントキャストの当たり判定高さを取得できる

var to = new Vector3(1f, 2f, 3f); //レイキャストが向かう地点の座標(ワールド座標)

var maxDistance = 5f; //レイキャスト長さ5mにする

var distance = Raycast_GetAllObjectDistance(mapScene.hero, from, to, maxDistance);
//プレイヤーからtoへ向けて5mの長さのレイキャストを発射しヒットしたものまでの距離をdistanceに格納する

 また、もう一つの例として、C#プログラムを割り当てたキャストイベントから、ある地点へレイキャストを発射する場合は次のように記述します。

using Microsoft.Xna.Framework; //Vector3型を使用するために冒頭で記述
var from = mapChr.getPosition(); //このキャストイベントの座標を取得
from.Y += mapChr.collisionStatus.GetHeight() * 0.5f;
//デフォルトでは足元が発射地点となっておりうまく動作しないためこのキャストイベントの当たり判定の半分の高さまで発射地点を持ち上げる
//ちなみにcollisionStatus.GetHeight()でイベントキャストの当たり判定高さを取得できる

var to = new Vector3(1f, 2f, 3f); //レイキャストが向かう地点の座標(ワールド座標)

var maxDistance = 5f; //レイキャスト長さ5mにする

var distance = Raycast_GetAllObjectDistance(mapChr, from, to, maxDistance);
//このキャストイベントからtoへ向けて5mの長さのレイキャストを発射しヒットしたものまでの距離をdistanceに格納する

2.2 第一引数"chr"について

 第一引数のMapCharacter型のchrにはマップ上に配置されている「キャストイベント」の情報を渡します。
 上記の例では、次の二つを使用しました。
 mapScene.hero:プレイヤーのキャストイベント
 mapChr:C#プラグインを割り当てしたキャストイベント 

「キャストイベント」(「キャスト」「イベント」の総称)はマップ上に配置されるものを指す用語です。"Unity"の「オブジェクト」、"Unreal Engine"の「アクター」に該当します。

2.3 レイキャストが反応するコリジョンタイプの設定

 サンプルコードでは、第三引数を(ushort)CollisionType.ALLとすることで、すべてのコリジョンタイプをヒット対象としています。

var result = chr.getRigidbody().getPhysicsBase().rayCast(Util.ToKmyVector(from), Util.ToKmyVector(to), (ushort)CollisionType.ALL, hit);

 これには他にも種類があります。詳細はBakinWikiに記載があります。

MAP:地形
MAP_SLOPE:坂・階段
MAP_OBJECT:物体
MAP_WATER:マップ端の見えない壁
MAP_ALL:上記全て
PLAYER:プレイヤー
EVENT:イベント
BULLET:未検証
PLAYER_SUB:未検証
EVENT_SUB:未検証
EVENT_ALL:未検証
ALL:上記全て

 これらを利用して、例えば、地形とイベントにのみヒットするようにするには次のように記述します。

var result = chr.getRigidbody().getPhysicsBase().rayCast(Util.ToKmyVector(from), Util.ToKmyVector(to), (ushort)(CollisionType.MAP_ALL | CollisionType.EVENT), hit);

2.4 ヒット対象から取得できる情報の種類

 サンプルコードでは、hit.distanceとすることで、ヒット対象との距離を取得するようにしています。

return hit.distance; //hit.distanceでレイキャストがヒットした対象との距離を取得できる

 これには、他にも種類があります。
 例えば、レイキャストがヒットした地点の座標を取得するにはhit.positionを使用して下記のように記述します。

return Util.ToXnaVector(hit.position);
//hit.positionでレイキャストがヒットした地点の座標を取得できる
//Util.ToXnaVectorはBakin専用のSharpKmyMath.Vector3型をMicrosoft.Xna.Framework.Vector3型に変換するもの

 また、レイキャストがヒットしたキャストイベントの名前を取得するには下記のように記述します。

var evt = hit?.node.getNotifyTarget() as MapCharacter; //キャストイベントを取得できる
return evt.rom?.name; //キャストイベントの名前を返す なおこの場合の戻り値はstring型

3. おわりに

 "RPG Developer Bakin"は、この記事を書いている時点(2024年6月9日)ではまだアーリーアクセスのゲーム開発ツールのため、C#プラグイン開発に関する情報はかなり少なく、まだまだ未開拓の領域です。
 今後、プラグイン開発者の方が増えていくと嬉しいなぁと思います。

 今回記載した内容は、私が実際に試して知った情報や"RPG Developer Bakin"の開発元である株式会社スマイルブーム様から直接ご教示頂いたものをまとめたものになります。
 「それはちがうよ!」というところがあれば、ぜひご指摘頂けると幸いです。
 ではでは。


この記事が気に入ったらサポートをしてみませんか?