Unity Term Book
コアとアーキテクチャ

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、スクリプト比較

例

PlayerEnemyTreasure

📚 Layer

目的

Physics と Camera 描画のためのオブジェクトグループ

数量

最大 32 レイヤー(0–7 は Unity 予約)、ビット 0–31

用途

Culling Mask、Collision Matrix、Raycast LayerMask

例

GroundProjectileUI

ハンズオン手順

1

新しい Tag/Layer を作成

Edit → Project Settings → Tags and Layers。Tags または Layers リストに追加。

2

GameObject に割り当て

Hierarchy で GO を選択 → Inspector 上部の Tag または Layer ドロップダウン。

3

Collision Matrix を設定

Edit → Project Settings → Physics → Layer Collision Matrix → 衝突させない組み合わせのチェックを外す。

4

Camera Culling Mask を設定

Camera を選択 → Inspector → Culling Mask → 描画する Layer を選ぶ(UI Camera は UI のみ、など)。

5

Raycast で LayerMask を使う

Physics.Raycast(origin, dir, distance, LayerMask.GetMask("Ground")) —— Ground だけヒット。

インタラクティブシミュレーター

GameObject をクリックして選択。Tag と Layer を変更し、Collision Matrix を確認して Raycast を試しましょう。

Hierarchy

GameObject を選択

Selected: None|GameObject をクリックして Tag/Layer を編集

コード例

基本

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")