【Unity】レイヤーとタグを徹底解説!Unityでオブジェクトを賢く分類・管理する基本

作成: 2025-12-10最終更新: 2026-07-13

レイヤーとタグの使い分け、衝突判定の制御、LayerMaskを使ったRaycast最適化など、オブジェクト管理の基本を解説。

「弾が背景の草にも当たってしまう」「シーン中の敵を全部探したいけど方法が分からない」——オブジェクトが数百、数千と増えてきたときに必ずぶつかるのが、この「分類と管理」の問題です。

Unityには、この問題を解決するために タグ(Tag)レイヤー(Layer) という2つの分類機能が用意されています。似ているようで役割はまったく違い、 タグは「識別名」、レイヤーは「機能のグループ分け」 です。この使い分けが分かると、衝突判定の最適化からオブジェクト検索まで、シーンの管理が一気に楽になります。

タグとレイヤーのイメージ。名札で個体を識別し、層でグループを分ける

この記事でわかること

  • タグとレイヤーの役割の違いと使い分けの基準
  • タグを使ったオブジェクト検索と衝突相手の識別
  • Layer Collision Matrixによる衝突判定の最適化
  • LayerMaskを使ったRaycastの絞り込み

Sponsored

タグ(Tag):オブジェクトの「識別名」として使う

タグ は、ゲームオブジェクトに付けることができる 識別用のラベル です。これは、スクリプトから特定の種類のオブジェクトを簡単に見つけ出すために最もよく使われます。

タグとレイヤーの役割の違いを表す比較図。タグは1体ずつに付ける名札(Player、Enemy、Item)、レイヤーは層ごとのグループ分け

タグの基本的な使い方

タグを設定するには、インスペクター上部のドロップダウンから既存のタグを選択するか、「Add Tag...」から新しいタグを作成します。注意点として、 1つのGameObjectに付けられるタグは1つだけ です。「敵でもありボスでもある」のような複数属性を持たせたい場合は、タグの多重付けではなく、自作の判定用コンポーネントやenumで表現します。

タグの最大の利点は、スクリプトから非常に直感的にオブジェクトを検索できる点です。

using UnityEngine;

public class TagSearchExample : MonoBehaviour
{
    void Start()
    {
        // シーン内の「Player」タグが付いたオブジェクトを一つ検索
        GameObject player = GameObject.FindWithTag("Player");
        if (player != null)
        {
            Debug.Log("プレイヤーオブジェクトを見つけました: " + player.name);
        }

        // シーン内の「Enemy」タグが付いたオブジェクトをすべて検索
        GameObject[] enemies = GameObject.FindGameObjectsWithTag("Enemy");
        Debug.Log("敵の総数: " + enemies.Length);
    }

    // 衝突時にタグを使って相手を識別する例
    private void OnTriggerEnter(Collider other)
    {
        // 衝突した相手のタグが「DamageZone」だったら
        if (other.gameObject.CompareTag("DamageZone"))
        {
            Debug.Log("ダメージゾーンに侵入しました!");
            // ここでプレイヤーのHPを減らすなどの処理を行う
        }
    }
}

GameObject.FindWithTag()はシーン全体を検索するため、頻繁に呼び出すとパフォーマンスに影響を与える可能性があります。さらにFindGameObjectsWithTag()は、 呼び出すたびに結果を入れる新しい配列を作る(メモリを確保する)ため、毎フレーム呼ぶとGC負荷の原因にもなります。Start()Awake()で一度検索して結果をキャッシュ(変数に保存)し、毎フレームのUpdate()では使わないように心がけましょう。

そもそも「今いる敵の一覧」のように 増減するリストを毎回タグで探し直すのは遠回り です。敵が出現・撃破されるタイミングで自分をリストへ登録・解除する Registry(登録簿)方式 の方が、速くて確実です(配列とListの記事RegisterEnemy/UnregisterEnemyがまさにこの形です)。タグ検索は「シーンに1つしかないものを最初に見つける」用途に絞るのがコツです。

補足: タグの比較にはother.gameObject.tag == "DamageZone"のような文字列比較ではなく、コード例のように CompareTag() を使いましょう。動作はほぼ同じですが、CompareTag()は存在しないタグ名を指定するとエラーで教えてくれるため、タイプミスに気づけます(==比較だと黙ってfalseになりバグの温床になります)。

Sponsored

レイヤー(Layer):機能的な「グループ分け」として使う

レイヤー は、タグとは異なり、主に 機能的な制御 のために使われます。特に重要な用途は以下の2つです。

  1. 物理演算(衝突判定)の制御: 特定のレイヤー同士の衝突を無視するように設定できます。
  2. カメラの描画制御: カメラが特定のレイヤーのオブジェクトだけを描画したり、逆に描画しなかったりするように設定できます。

レイヤーを使った衝突判定の最適化

最も強力なレイヤーの使い方は、衝突判定の制御です。例えば、「背景オブジェクト」と「背景オブジェクト」同士の衝突は不要な場合、これらを同じレイヤーに設定し、衝突を無効にすることで、物理演算の負荷を大幅に軽減できます。

  1. レイヤーの作成: Edit -> Project Settings -> Tags and Layersで新しいレイヤー(例:Background)を作成します。
  2. オブジェクトへの適用: 背景オブジェクトにBackgroundレイヤーを適用します。
  3. 衝突の無効化: Edit -> Project Settings -> Physics(またはPhysics 2D)を開き、Layer Collision Matrix(レイヤー衝突行列)で、BackgroundBackgroundが交差するチェックボックスのチェックを外します。
レイヤーDefaultPlayerEnemyBackground
Default
Player
Enemy
Background(チェックを外す)

この設定により、Backgroundレイヤーに属するオブジェクト同士は、たとえ接触しても物理的な衝突判定を行わなくなります。

Layer Collision Matrixの効果の実例。プレイヤーと背景は衝突するが、チェックを外したBackground同士は衝突判定されずすり抜ける

レイヤーマスクを使ったRaycastの効率化

Raycast(レイを飛ばして衝突を検出する処理)を行う際にも、レイヤーは非常に重要です。レイヤーマスクを使用することで、 特定のレイヤーに属するオブジェクトだけ を対象にRaycastを実行でき、不要な判定をスキップして処理を高速化できます。

LayerMaskを使ったRaycastの図。レイはBackgroundレイヤーの木を素通りし、マスクで指定したEnemyレイヤーの敵にだけヒットする
using UnityEngine;

public class RaycastExample : MonoBehaviour
{
    // インスペクターから設定できるように public 変数として宣言
    public LayerMask targetLayer;

    void Update()
    {
        // 前方にRayを飛ばす
        Ray ray = new Ray(transform.position, transform.forward);
        RaycastHit hit;

        // Raycastを実行。第3引数にLayerMaskを指定する
        // ここでは targetLayer に設定されたレイヤーのオブジェクトのみを検出する
        if (Physics.Raycast(ray, out hit, 10f, targetLayer))
        {
            Debug.Log("レイヤーマスク内のオブジェクトにヒットしました: " + hit.collider.name);
        }
    }
}

LayerMask型の変数は、インスペクター上でドロップダウンメニューとして表示され、どのレイヤーを対象にするかをチェックボックスで簡単に設定できます。コード内でマジックナンバー(数値)を使うよりも、この方法で設定する方が管理しやすく、ミスも減ります。

Sponsored

初心者が躓きやすいポイント

タグとレイヤーの混同

最もよくある間違いは、タグとレイヤーの用途を混同することです。

  • タグ: 「これは敵だ」「これはアイテムだ」という識別に使う。
  • レイヤー: 「このオブジェクトは衝突判定をしない」「このオブジェクトは描画しない」という機能制御に使う。

機能制御(特に物理演算)が必要な場合はレイヤーを、単なる識別や検索が必要な場合はタグを使う、と明確に使い分けることで、コードと設定が整理されます。

「Sorting Layer」は別物

2Dゲームでよく見かける Sorting Layer は、名前は似ていますが この記事のレイヤー(物理・描画制御用のLayer)とはまったく別の仕組み です。Sorting Layerはスプライトの 描画の前後関係(どちらが手前に描かれるか)を決めるためのもので、衝突判定には一切関係ありません。「Sorting Layerを分けたのに衝突してしまう/衝突しなくならない」と混乱したら、この2つを取り違えていないか確認してください。

レイヤーマスクのビット演算

スクリプト内でレイヤーマスクを扱う際、レイヤー番号(0〜31)を直接使うのではなく、ビット演算(1 << layerNumber)を使う必要があります。

例えば、レイヤー番号10番のレイヤーだけを対象にしたい場合、以下のように記述します。

// レイヤー番号10のレイヤーマスクを作成
int layerNumber = 10;
int layerMask = 1 << layerNumber;

// Raycastの実行
Physics.Raycast(ray, out hit, 10f, layerMask);

これは、Unityのレイヤーマスクが32ビットの整数値で管理されており、各ビットが対応するレイヤーの有効/無効を表しているためです。このビット演算の仕組みを理解しておくと、複数のレイヤーを組み合わせる(例:layerMask = (1 << 8) | (1 << 9);)といった応用も可能になります。

Sponsored

おまけ:先に知っておくと良いこと

タグとレイヤーを使いこなせるようになったら、次はこのあたりの知識が活きてきます。

  • Raycastをもっと深く: レイの飛ばし方には球状のSphereCastや全ヒット取得のRaycastAllなど多くのバリエーションがあります。Physics.Raycast徹底解説の記事 でマスターできます。
  • 衝突イベントの受け取り方: レイヤーで「衝突するか」を制御した後は、OnCollisionEnter/OnTriggerEnterで「衝突したら何をするか」を書きます。OnTriggerとOnCollisionの記事 が参考になります。
  • 効果を数字で確認する: レイヤー最適化の効果は体感では分かりにくいもの。Unity Profilerの記事 で物理演算の負荷を実測できるようになると、最適化が楽しくなります。

まとめ

Unityのタグとレイヤーを効果的に活用することで、シーン内のオブジェクト管理は劇的に改善されます。本記事で学んだ要点は以下の通りです。

  • タグはオブジェクトの識別に特化しており、GameObject.FindWithTag()などによる検索や、衝突時の相手の種類の判定に利用します。
  • レイヤーはオブジェクトの機能制御に特化しており、特に 物理演算(衝突判定)カメラの描画の最適化に不可欠です。
  • レイヤーを使った衝突判定の制御は、Project SettingsPhysicsにあるLayer Collision Matrixで行い、不要な計算を省略してパフォーマンスを向上させます。
  • Raycastなどの処理では、LayerMaskを使用することで、特定のレイヤーのオブジェクトのみを対象にでき、処理を効率化できます。
  • スクリプトでレイヤー番号を扱う際は、ビット演算(1 << layerNumber)を用いてLayerMaskを作成することが基本です。

これらの基本をマスターし、あなたのUnityプロジェクトをより整理され、高性能なものにしてください。