レイヤーマスクを使いこなす!必要なやつのみ当たり判定取る!【Unity】
色んなものが重なっている時に必要なものだけ当たり判定が取りたい、そんなときはレイヤーマスクを使います!実際に動くもの、レイヤーマスクがどんなものか、どんなものかはよくわかってないけど簡単に使いたい!などをそれぞれまとめたいと思います。
目次
LayerMaskを使った当たり判定サンプル
まずはちゃんと動くサンプルを確認していただきましょう。思い出せる人はこれ見て思い出してください。
当たり判定を取る条件など
下記画像のA点から平面に向かってRayを飛ばし当たり判定を取ります。今回は一番奥の赤い平面のとの当たり判定を取りたいとします。今回のサンプルではA点の位置と、Rayを飛ばす方向は合っているとします。
各ゲームオブジェクトのレイヤーは次の様になっています。
オブジェクト | レイヤー名 |
赤いQuad | Red |
青いQuad | Blue |
緑のQuad | Green |
実際のプログラム
上記の条件下で、緑と青い平面をスルーして赤い平面にのみ当たり判定を取りたい場合、下記のようなプログラムになります。下記プログラムはA点に存在するGameObjectにアタッチされているとします。
using UnityEngine;
public class SearchRay : MonoBehaviour
{
private void Start()
{
LayerMask layerMask = 1 << LayerMask.NameToLayer("Red");
if (Physics.Raycast(
transform.position,
new Vector3(0f, 0f, 1f),
out RaycastHit hit,
Mathf.Infinity,
layerMask))
{
Debug.Log(hit.collider.gameObject.name);
}
}
}
実行結果はこんな感じ
LayerMask(レイヤーマスク)を使う注意点など
ここからはLayerMaskについて触れていきましょう。どういったものなのか、扱う際の注意など。あとはどういった知識があれば良いのかなどについてお話します。
レイヤーマスクっどういうことが出来る?どういう値なの?
レイヤーマスクを利用することで主に以下のことが出来ます。
- カメラに表示するか場合、対称のレイヤーのみを表示する
- 当たり判定などで特定のレイヤーのみ当たり判定を行う
レイヤーを設定する
レイヤーは最大32個まで設定することが可能です。そのうち5つは固定で決まっており、残りの27個を自由に設定することが出来ます。レイヤーの種類を追加設定を行うには、Edit>Project Settingsから[Tags and Layers]からLayersを開きます。User Layer(数字)と書いてある横のテキストボックスに文字列を入力してください。下記画像はUser Layer6~8にそれぞれRed,Blue,Greenというレイヤーを追加した状態です。
レイヤーの追加が完了したら、レイヤーを適応したいゲームオブジェクトを選択肢、インスペクターから設定を行います。インスペクター上部のレイヤータブから設定したいレイヤーを選択することで変更が出来ます。この時先程のレイヤーの追加を行っていないとプルダウンメニューの中には表示されませんので注意してください。
カメラの表示制限について
カメラには、レイヤーを使うことで写すオブジェクトを制御することが可能です。カメラに写すレイヤーの設定はカメラのインスペクターのCulling Maskから設定を行うことが出来ます。Culling Maskでは登録済みのレイヤーが一覧に表示されます。カメラに写したいレイヤーにチェックが入っています。表示非表示を行いたいものにチェックを入れてみてください。
では、実際に上記設定を2パターン変化つけてみたいと思います。一つはそのまま、もう一つはBlueのレイヤーのみチェックを外した状態で比べた結果が下記画像です。ちょっと分かりづらいですがシーンビューには存在してますが、カメラのプレビュー(実際のゲーム画面)から消えています。
当たり判定の制限について
Unityはシーン内にCubeを置いたりするだけで物理的なシミュレーションを行うことが出来ます。床(Plane)の上に箱(Cube)を置くと床の上に箱が乗っかります。これをレイヤーの設定を変更するだけで床と箱との当たり判定を無効化することが可能です。
設定を行うには、Edit>Project SettingsからPhysics(2Dの場合はPhysics2D)の下の方にあるLayer Collision Matrixを使って行うことが出来ます。追加されたレイヤーが一覧に表示され、各レイヤーごとの交点のチェックボックスを外すと当たらなくなります
下図の例ではすべてのレイヤーと当たり判定があるパターンとレイヤーRedのみ当たり判定があるような設定を行ったパターンを並べたものです。プログラムを変更しなくてもCollisionMatrixの設定だけで下図のような当たり判定を実演することが出来ます。
レイヤーマスクをプログラムで設定する
プログラムでレイヤーマスクを設定する場合、いくつか知っておかなくては理解が難しいポイントがあります。実際に設定を行うサンプルを交えつつ、自分のプログラムへの適応も試みてください。
レイヤーマスクはビット演算子!?
レイヤーマスクはビット演算子として扱われます。ビット演算子とは簡単に言うと2進数で表される変数のことです。いくつか省略しますが下記数字はビット演算子では下記のように表されます。
int 10進数 | ビット演算子 2進数 |
0 | 00000000 |
1 | 00000001 |
2 | 00000010 |
3 | 00000011 |
4 | 00000100 |
5 | 00000101 |
という感じでビット演算子とint型の変数などを比べるとこのようになります。今回は2進数についての細かい話は省きますが、ビット演算子で数字を扱うことで普通の数字とは違う取り扱いが出来ます。
ビット演算子では各ビットごとにフラグの判定を行うことが出来ます。例えば先程設定したレイヤーの設定だと各ビットは次のように対応しています。(実際には32ビットありますが、ここでは8ビットまでしか表示してません)
上の例ではすべて「0」で入れてますが、先程のCulling Maskなどでチェックボックが入っているものは対応したビットが1になっている状態です。0と1が混ざることでどのビットが立っているかの組み合わせによって状態を判断することが出来るのがビット演算子の最大の魅力です。
レイヤー名からレイヤーマスクを指定する
プログラムで使う場合、レイヤーマスクのビットを8だから01000とか覚えておいて、それを利用するのはあまり現実的ではありません。登録時に何番目のビットというのを覚えておくこと自体は悪くないですが実際にプログラムで利用するときはそのレイヤーの名前からビット演算子を算出します。算出するには名前からレイヤー番号を取得するメソッドと、シフト演算子というものを利用して求めます。
欲しい物 | 求める方法 | 備考 |
レイヤー番号 | LayerMask.NameToLayer(“Red") | レイヤー名Redの レイヤー番号が欲しい |
LayerMask | 1 << (レイヤー番号) | レイヤー番号が3の場合 00001000 |
すまねぇ、ビット演算子はさっぱりという方向け
ここからはプログラムでビット演算子が上手く操作出来ない人向け。ビット演算子やシフト演算子を利用することで様々な組み合わせを表現することが出来るのですが、覚えることがいくつか出てきます。が、そういうのめんどい!という方はインスペクターをうまく利用することで簡単に扱うことが出来ます。
インスペクターを利用してセットする
インスペクターで設定を行い利用するには、まず下記のようなメンバー変数を用意してください。
using UnityEngine;
public class EasyLayerMask : MonoBehaviour
{
public LayerMask m_layerMask;
}
スクリプトを用意出来たらどこかのGameObjectに貼り付けてみてください。するとインスペクターのメンバー変数部分が次のようになっています。
カメラなどで見た、登録済みのレイヤーを選択できる様子が伺えると思います。一つだけ選択されているときは対称のレイヤー名、2つ以上の組み合わせになるとMixedという表示に切り替わります。ここで事前にセットしておくことで簡単に準備することが出来ます。
あとはプログラムなどでレイヤーマスクが必要なところに先程用意した変数を代入してください。