初めに
レイヤーの変更や追加の方法、GameObject.layer や LayerMask などスクリプトからレイヤーを扱う方法をまとめます。
レイヤー
レイヤーとは
レイヤーを使うことで、カメラが描画するレイヤーやレイキャストに使用するレイヤーを選択することができます。
各レイヤーには0から31までの 32個の整数によって、レイヤー番号が割り当てられています。
レイヤーの変更・追加
オブジェクトの Inspector からレイヤーを変更できます。
Add Layer... をクリックすると、Inspector に Tag & Layers(下の画像のような画面)が表示され、レイヤーを追加することができます。
Culling Mask を使って、カメラに描画するレイヤーを選択する
Camera の Rendering > Culling Mask からカメラに描画するレイヤーを選択することができます。チェックが入っているレイヤーは描画され、チェックが入っていないレイヤーは描画されません。
GameObject.layer
GameObject.layer からレイヤーを取得、変更することができます。返り値は int であり、割り当てられているレイヤー番号が返ってきます。
//public int layer ; //割り当てられている整数を代入 //Defaultレイヤーに0が割り当てられているときは, 下のようにすればDefaultに変更可能 gameObject.layer = 0;
※通常は、整数を直接代入せず、LayerMask.NameToLayer を使い、レイヤー名を整数に変換したものを代入します。(後述)
LayerMask
LayerMask は Physics.Raycastで使用するレイヤーを指定します。LayerMask を使うことで、Ray と衝突判定を行うレイヤーを選択することができます。また、複数のレイヤーが含まれるレイヤーマスクを作ることもできます。
LayerMask.value
LayerMask.value は、レイヤーマスクを整数に変換した値です。注意点は各レイヤーに割り当てられたレイヤー番号ではないということです。
(レイヤー番号が i, j, k のレイヤーが含まれたレイヤーマスクの値)
2^i + 2^j + 2^k
Inspector からレイヤーマスクを取得する
LayerMask を public で定義することで、Inspector からそのレイヤーマスクに含むレイヤーを選択できます。下の画像のように複数選ぶことも可能です。
public LayerMask obstacleLayerMask; //InspectorからLayerMaskを選択できるようにしている
LayerMask.GetMask:スクリプトからレイヤーマスクを取得する
public にせず、スクリプトからこの LayerMask を取得する場合は、LayerMask.GetMask を使います。
//public static int GetMask (params string[] layerNames); using UnityEngine; public class Example : MonoBehaviour { // レイヤー名を指定するための変数 private string[] layerNames = { "Default", "TransparentFX", "Water" }; //レイヤーの名前を入力 // レイヤーマスクを取得するための変数 private LayerMask layerMask; private void Start() { // レイヤーマスクを取得] // Defalut:0, TransparentFX:1, Water:4 のとき, 2^0+2^1+2^4=19が返ってくる layerMask = LayerMask.GetMask(layerNames); } }
Physics.Raycast
Raycast については、下の記事で説明しております。Physics.Raycast についても書いておりますので、そちらをご覧ください。
LayerMask と Physics.Raycast を使って衝突を判定する
Physics.Raycast の引数に LayerMask を入れることでどのレイヤーについて判定したいのか、選択することができます。
(例)
using UnityEngine; public class LayerTest : MonoBehaviour { public float moveSpeed; public LayerMask obstacleLayerMask; //InspectorからLayerMaskを選択できるようにしている private void Update() { float horizontalInput = Input.GetAxis("Horizontal"); float verticalInput = Input.GetAxis("Vertical"); Vector3 movement = new Vector3(horizontalInput, verticalInput, 0f); Vector3 targetPosition = transform.position + movement * moveSpeed * Time.deltaTime; RaycastHit hit; if (Physics.Raycast(transform.position, targetPosition - transform.position, out hit, movement.magnitude * moveSpeed * Time.deltaTime, obstacleLayerMask)) //obstacleLayerMaskで選択したレイヤーとの衝突を検知 { // 障害物との交点から移動可能な方向を計算する Vector3 moveDirection = Vector3.ProjectOnPlane(movement, hit.normal).normalized; targetPosition = transform.position + moveDirection * moveSpeed * Time.deltaTime; } transform.position = targetPosition; } }
LayerMask.LayerToName、LayerMask.NameToLayer
LayerToName は整数をレイヤー名に、NameToLayer はレイヤー名を整数に変換する関数です。
(LayerToName)
//public static string LayerToName (int layer); using UnityEngine; public class Example : MonoBehaviour { void Start() { // Prints the name of the layer 1 Debug.Log(LayerMask.LayerToName(1)); //デフォルトでは、1が割り当てられているTransparentFXが返ってくる } }
(NameToLayer)
//public static int NameToLayer (string layerName); using UnityEngine; public class Example : MonoBehaviour { void Start() { Debug.Log(LayerMask.NameToLayer("TransparentFX")); //デフォルトでは、TransparentFXが割り当てられている1が返ってくる } }
※NameToLayerの引数にレイヤー名以外を入力すると、-1が返ってきます。
レイヤーを全取得する
下のスクリプトを使うことで、レイヤーを全取得することができます。
各レイヤーに0から31までの整数が割り当てられていることと LayerMask.LayerToName を使っています。
/// <summary> /// Layer名をキー、Layer番号を値とするDictionaryを返します。 /// </summary> public static Dictionary<string, int> GetAllLayers() { Dictionary<string, int> layers = new Dictionary<string, int>(); for (int i = 0; i < 32; i++) { string layerName = LayerMask.LayerToName(i); if (!string.IsNullOrEmpty(layerName)) { layers.Add(layerName, i); } } return layers; }