この記事でのバージョン
Unity 5.1.0f3 Personal
RayCastシリーズ
1.使い方
2.衝突するオブジェクトの制限
3.Rayを画面に表示
4.2Dで使う
はじめに
RayCastシリーズ、前回は使い方の記事でした。
2回目の今回は衝突するオブジェクトの制限方法についてです。
Ignore RayCast
手っ取り早くRayとの衝突をしないようにするにはLayerをIgnore RayCastにすればokです。
全てのRayに当たらなくなるので、汎用性はありませんがとにかく楽。
LayerMask
任意のレイヤーとだけ衝突させたいと言った場合にはレイヤーマスクを使います。
以下の通り、レイヤーマスクを作成し、Raycast時に引数に与えると、
衝突するオブジェクトを制限出来ます。
int layerMask = 0; Physics.Raycast(ray, out hit, Mathf.Infinity, layerMask);
ちなみに0の時は全てのレイヤーと衝突しなくなります。
また、マスクを指定すると前述したIgnore RayCastにも衝突できるようになるので注意が必要です。
このレイヤーマスクは、作成する方法がいくつかあるので、
以下の例を用いて説明していきます。
そもそも、ビット演算やビットマスクが分からない方にはこちらがオススメ。
分からなくても使えるとは思います。
ビット演算でレイヤーマスクを作る
単純なやり方だとビット演算を用います。
//Corgiレイヤーとだけ衝突する int layerMask = 1 << 8;
//Corgi、Shibaレイヤーとだけ衝突する int layerMask = 1 << 8 | 1 << 9;
//Corgiレイヤーとだけ衝突しない int layerMask = ~(1 << 8);
<< でビットシフトを行いマスクを作成します。
複数ある場合は | で区切り、
条件を反転させる場合は ~ を使います
分かり難いし、ミスも起き易いんですけどね…
ただし、条件を反転する ~ は他の方法でも使うので覚えとくと便利です。
変換メソッドでレイヤーマスクを取得する
LayerMask.GetMaskというメソッドで、
レイヤー名の配列からマスクを取得するパターンです。
//Corgi、Shibaレイヤーとだけ衝突する int layerMask = LayerMask.GetMask(new string[] {"Corgi", "Shiba"});
//Corgiレイヤーとだけ衝突する int layerMask = LayerMask.GetMask(new string[] {LayerMask.LayerToName(8)});
文字列でレイヤー名を直接指定するか、
LayerToNameを使ってレイヤー番号からレイヤー名を作成し、指定します。
ビット演算を行うよりは分かり易くなりましたが、
ミスの起き易さは大して変わっていない気がしますね。
Inspectorからレイヤーマスクを指定する
スクリプト上でマスクを作成するのではなく、Inspectorから指定する事も出来ます。
[SerializeField]
private LayerMask layerMask;
public LayerMask LayerMask;
上記のようにSerializeField指定か、public変数にしてLayerMaskを
Inspectorに表示すると、プルダウンで指定できるようになります
分かり易いですし、ミスも少なそうですが、
複数条件時はちょっとめんどくさくなりそうです。
定数クラスでレイヤーマスクを指定
毎回レイヤーマスクを作るのではなく、あらかじめレイヤーマスクを定数として自動で宣言しておき、
それを使うパターンです。私が実際にやってる方法でもあります。
上記の記事の通り定数クラスを自動生成すると、以下のようにマスクを指定できるようになります。
//Corgi、Shibaレイヤーとだけ衝突する int layerMask = LayerMaskNo.CORGI + LayerMaskNo.SHIBA;
簡単かつ、分かり易い、さらにミスも起こり難いんじゃないでしょうか……!
トリガーは検出しない
番外編としてトリガーを検出しない方法です。
デフォルトではコライダーのIs Triggerにチェックを入れたモノにもRayは反応しますが、
[Edit]-[Project Settings]-[Physics]の
Raycasts Hit Triggers のチェックを外せば、トリガーは検出しなくなります。
検出対象を分けるのはマスクを使った方がいい気がしないでもないです。
おわりに
とりあえず今回はこの辺で、
次回はRayを画面に表示して確認する、とかそんな感じになると思います!