読者です 読者をやめる 読者になる 読者になる

(:3[kanのメモ帳]

個人ゲーム開発者kan.kikuchiのメモ的技術ブログ。月木更新でUnity関連がメイン。

RayCastその2、衝突するオブジェクトの制限【Unity】

Unity

このエントリーをはてなブックマークに追加

この記事でのバージョン
Unity 5.1.0f3 Personal


RayCastシリーズ
1.使い方
2.衝突するオブジェクトの制限
3.Rayを画面に表示
4.2Dで使う


はじめに

RayCastシリーズ、前回は使い方の記事でした。



2回目の今回は衝突するオブジェクトの制限方法についてです。


Ignore RayCast

手っ取り早くRayとの衝突をしないようにするにはLayerをIgnore RayCastにすればokです。


f:id:kan_kikuchi:20150720064249j:plain


全てのRayに当たらなくなるので、汎用性はありませんがとにかく楽。


LayerMask

任意のレイヤーとだけ衝突させたいと言った場合にはレイヤーマスクを使います。

以下の通り、レイヤーマスクを作成し、Raycast時に引数に与えると、

衝突するオブジェクトを制限出来ます。

int layerMask = 0;
Physics.Raycast(ray, out hit, Mathf.Infinity, layerMask);


ちなみに0の時は全てのレイヤーと衝突しなくなります。

また、マスクを指定すると前述したIgnore RayCastにも衝突できるようになるので注意が必要です。


このレイヤーマスクは、作成する方法がいくつかあるので、

以下の例を用いて説明していきます。


f:id:kan_kikuchi:20150720065014p:plain


そもそも、ビット演算やビットマスクが分からない方にはこちらがオススメ。

分からなくても使えるとは思います。


ビット演算でレイヤーマスクを作る

単純なやり方だとビット演算を用います。

//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に表示すると、プルダウンで指定できるようになります


f:id:kan_kikuchi:20150722080252p:plain


分かり易いですし、ミスも少なそうですが、

複数条件時はちょっとめんどくさくなりそうです。


定数クラスでレイヤーマスクを指定

毎回レイヤーマスクを作るのではなく、あらかじめレイヤーマスクを定数として自動で宣言しておき、

それを使うパターンです。私が実際にやってる方法でもあります。



上記の記事の通り定数クラスを自動生成すると、以下のようにマスクを指定できるようになります。

//Corgi、Shibaレイヤーとだけ衝突する
int layerMask = LayerMaskNo.CORGI + LayerMaskNo.SHIBA;


簡単かつ、分かり易い、さらにミスも起こり難いんじゃないでしょうか……!


トリガーは検出しない


番外編としてトリガーを検出しない方法です。

デフォルトではコライダーのIs Triggerにチェックを入れたモノにもRayは反応しますが、

[Edit]-[Project Settings]-[Physics]


f:id:kan_kikuchi:20150719191052j:plain


Raycasts Hit Triggers のチェックを外せば、トリガーは検出しなくなります。


f:id:kan_kikuchi:20150719191120j:plain


検出対象を分けるのはマスクを使った方がいい気がしないでもないです。


おわりに

とりあえず今回はこの辺で、

次回はRayを画面に表示して確認する、とかそんな感じになると思います!