Tag & Layer
Tag はスクリプト識別用のラベル(CompareTag)、Layer は Physics 衝突・Camera Culling・Raycast の LayerMask でオブジェクトをグループ化します。Collision Matrix の設定と Tag/Layer の正しい使い分けの基礎を学べます。
想像してみてください...
Tag は名札のようです——「Player」「Enemy」「Treasure」——警備員が即座に認識・反応できます(CompareTag)。Layer は建物のゾーン分け図面のようで、許可された階だけ入れる(Camera Culling Mask)、どの部屋同士が物理的に触れ合えるかも決まります(Physics Layer Collision Matrix)。
概念の詳細
Tag は GameObject 上の文字列ラベル(GO ごとに 1 つ)です。
文字列割り当てを避けるため gameObject.tag == “Player” より
gameObject.CompareTag(“Player”) を優先します。組み込みタグ:
Untagged, Respawn, Finish, EditorOnly, MainCamera, Player, GameController。
Layer は整数 0–31(最大 32 層)です。各 Layer は LayerMask(32-bit ビットマスク)の 1 ビットです。 Layer が担う役割:(1) Camera Culling Mask——選んだ Layer だけ描画; (2) Physics Layer Collision Matrix——どの Layer 同士が衝突するか; (3) Raycasting LayerMask——レイが当たる Layer。
LayerMask:
LayerMask.GetMask(“Enemy”, “NPC”) で結合。~ で反転(除外):
~LayerMask.GetMask(“Player”) = Player 以外の全 Layer。
良い習慣: Layer 名はオブジェクト名ではなく役割で付ける。 Edit → Project Settings → Tags and Layers で作成。例: Ground, Projectile, Interactable, UI, PostProcess。
比較:Tag vs Layer
🏷 Tag
目的
スクリプトでオブジェクト種別を識別(CompareTag)
数量
無制限(文字列)。各 GO は Tag を 1 つだけ持つ
用途
OnTriggerEnter、FindWithTag、スクリプト比較
例
📚 Layer
目的
Physics と Camera 描画のためのオブジェクトグループ
数量
最大 32 レイヤー(0–7 は Unity 予約)、ビット 0–31
用途
Culling Mask、Collision Matrix、Raycast LayerMask
例
ハンズオン手順
新しい Tag/Layer を作成
Edit → Project Settings → Tags and Layers。Tags または Layers リストに追加。
GameObject に割り当て
Hierarchy で GO を選択 → Inspector 上部の Tag または Layer ドロップダウン。
Collision Matrix を設定
Edit → Project Settings → Physics → Layer Collision Matrix → 衝突させない組み合わせのチェックを外す。
Camera Culling Mask を設定
Camera を選択 → Inspector → Culling Mask → 描画する Layer を選ぶ(UI Camera は UI のみ、など)。
Raycast で LayerMask を使う
Physics.Raycast(origin, dir, distance, LayerMask.GetMask("Ground")) —— Ground だけヒット。
インタラクティブシミュレーター
GameObject をクリックして選択。Tag と Layer を変更し、Collision Matrix を確認して Raycast を試しましょう。
Hierarchy
GameObject を選択
コード例
基本OnTriggerEnter 内で Tag によりオブジェクトを識別する。
using UnityEngine;
public class TreasureChest : MonoBehaviour
{
private void OnTriggerEnter(Collider other)
{
// CompareTag does not allocate a string — better than ==
if (other.CompareTag("Player"))
{
Debug.Log("Player collected the treasure chest!");
gameObject.SetActive(false);
}
}
}
// Find every Enemy in the scene by Tag
GameObject[] enemies = GameObject.FindGameObjectsWithTag("Enemy");
foreach (var e in enemies) e.GetComponent<EnemyAI>().Alert();コード例
上級Raycast での LayerMask と、ランタイムでの Layer 変更。
using UnityEngine;
public class PlayerGroundCheck : MonoBehaviour
{
[SerializeField] private float checkDistance = 0.1f;
// Build LayerMask from names — cache it, do not rebuild every frame
private readonly int _groundMask = LayerMask.GetMask("Ground", "Platform");
public bool IsGrounded =>
Physics.Raycast(transform.position, Vector3.down, checkDistance, _groundMask);
void Update()
{
if (IsGrounded)
GetComponent<Rigidbody>().drag = 5f; // friction while grounded
else
GetComponent<Rigidbody>().drag = 0f; // no drag in the air
}
// Change Layer at runtime (e.g. ghost through walls)
public void SetGhostMode(bool ghost)
{
gameObject.layer = LayerMask.NameToLayer(ghost ? "Ghost" : "Player");
}
}📌 要点
- ▸Tag = スクリプトでの識別;Layer = Physics と Camera の制御
- ▸GC 割り当て回避のため
CompareTag()をtag ==より優先 - ▸LayerMask はビットマスク——マジックナンバーではなく
GetMask() - ▸Layer は最大 32;不要な Collision Matrix ペアはオフ
⚠️ よくあるミス
❌ gameObject.tag == "Player" を使う
呼び出しごとに文字列割り当て → GC 圧力
✅ gameObject.CompareTag("Player")
❌ ハードコードした layer ビット:layerMask = 8
Layer 順序が変わると壊れる
✅ LayerMask.GetMask("Ground")