【Unity】Layer(レイヤー)とは?衝突や表示処理の作用をグルーピングする機能

Layerとは? Unity

こんにちは、ともくんのゲーム作り部屋にようこそ!

このページでは、

「UnityのLayerってなに?」

「Layerを設定するとどういうことができるの?」

というお悩みの方に向けた内容となっています。

Unityには、Layerと呼ばれるオブジェクト毎のグルーピングを設定する機能があります。

このLayerは、他のオブジェクトやカメラに対して、そのグループのオブジェクトがどのように作用するかを決めることができます。

例えば、設定したLayerのオブジェクトでの衝突判定を行うかどうかや、カメラで特定のLayerのオブジェクトを表示させるかどうかなどを設定することができます。

そこでこのページでは、UnityのLayerについて、どのような機能なのか、またLayerを使うことでどんなことができるのか、をまとめていきます。

この記事を書いた人

ゲーム作りを学び始めた一児のパパです。
このブログは、子供から「ゲームを作ってみたい!」と言われ、非プログラマーでゲーム作りをしたことない僕が、ゲーム作りの本を読んで独学でゲーム開発を学んでいるブログです。
同じように初めてゲーム作りをしている方と一緒に学んでいけるようなブログに出来たらいいなと思っています。
また、「このコードはおかしい」とか「もっと良い書き方があるよ!」などあれば、どんどん指摘して頂けると助かります。

Layer(レイヤー)とは?

まずは、UnityのLayerという機能がどういうものなのかを紹介していきます。

衝突や表示に対する作用をグルーピングする機能

Unityでは、オブジェクト毎に「Layer」というものを設定することができます。

このLayerとは、そのオブジェクトがどのような作用を行うかを決めるグルーピングの機能になっています。

そして、Layerを使ってグルーピングすることで、

  • 特定のLayerのオブジェクトとは衝突判定を行わない
  • 特定のLayerのオブジェクトはカメラで描画しない

などのことができるようになります。

例えば、オブジェクトによって「A」「B」というLayerを設定していた場合に、「A」同士のオブジェクトの衝突判定は行うけど、「A」「B」のオブジェクトがぶつかっても衝突判定が行われないように設定することができます。

このように、オブジェクトにLayerを設定しておくことで、そのオブジェクトへの処理や作用を一括で管理することができます。

Sorting LayerやRendering Layerとの違い

Unityには、Layerと同じような名称の機能として、「Sorting Layer」「Rendering Layer」という機能がありますが、どちらもLayerとは機能自体が異なります。

「Sorting Layer」は、2Dオブジェクトで指定できる項目で、オブジェクトをレンダリングする順番を決めている設定です。

もう少し簡単に言えば、オブジェクトを前に表示させるか、後ろに表示させるかを決めるのが、Sorting Layerの機能となっています。

一方で、「Rendering Layer」はLightオブジェクトに指定することができる設定項目で、その照明の影響をオブジェクトで受けるかどうかを決めることができる設定です。

例えば、Aの照明をオブジェクトに当てたいけど、Bの照明は当てたくないといった場合に、Rendering Layerでグルーピングしてあげることで、その作用を実現することができます。

それぞれの機能を簡単にまとめると、

  • 「Layer」:衝突や表示処理においてオブジェクトをグルーピングする
  • 「Sorting Layer」:2Dオブジェクトのレンダリングする順番を決める
  • 「Rendering Layer」:Lightオブジェクトをグルーピングして照明の影響を決める

となっています。

Layer(レイヤー)の使い方

ここからは、実際にUnityでのLayerの使い方をまとめていきます。

Layerの設定方法

Layerを設定する際は、インスペクターウィンドウから設定するか、スクリプトから設定することができます。

なお、一つのオブジェクトに設定できるLayerは一つだけとなっています。

Layerをインスペクターウィンドウから設定する

インスペクターウィンドウからLayerを設定する場合は、ゲームオブジェクトを選択した状態でインスペクターウィンドウの以下の箇所にあるLayerを設定します。

初期設定では「Default」になっていますが、選択してLayerを変更することができます。

また、Layerには、Unityで初めから設定されているもの(Builtin Layer)以外に、自分で名前を付けて新しいLayer(User Layer)を作ることができます。

Layerを作る場合は、まず「Add Layer…」をクリックして、

表示されたTag & Layersの画面で、空いているUser Layerの項目に名前を付けてあげます。

そして、もう一度インスペクターウィンドウに戻り、Layerの項目を選択すると、先ほど作ったLayerが表示され選択することができます。

Layerをスクリプトから設定する

スクリプトからLayerを設定する場合は、オブジェクトにアタッチしているスクリプトであれば、以下のように記述することでLayerを変更することができます。

using UnityEngine;

public class Cube : MonoBehaviour
{
    void Start()
    {
        this.gameObject.layer = 3;  // Layerを「3」番のものに変更する
    }
}

例えば、ゲーム実行前は「Default」のLayerになっていますが、

上のスクリプトをアタッチした状態でゲームを実行してみると、

スタートと同時にLayerを「3」番で設定したものに変更することができています。

Layer機能の実用例

UnityのLayer機能を使うことで、

  • コライダーによる衝突判定をLayer毎に変更
  • Raycastによる衝突判定をLayer毎に変更
  • カメラによる描画処理をLayer毎に変更

主に上記のようなことができるようになります。

ここからは、それぞれの実装方法について紹介していきます。

コライダーによる衝突判定をLayer毎に変更する

Unityでは、コライダーを付けたオブジェクト同士を当てることで、当たり判定を行うことができますが、特定のLayerのオブジェクトに対しての衝突判定の有無を変更することができます。

ここでは、2Dゲームで三角と四角のオブジェクトをシーン内に配置して、丸いオブジェクトを動かして衝突させると、三角のオブジェクトは消えるけど、四角のオブジェクトは消えないという処理を作ってみます。

まず、Layerの機能を使わずに、三角と四角のオブジェクトにはどちらもコライダーコンポーネント、また丸いオブジェクトに対しては、Rigidbodyコライダーのコンポーネントを付けておきます。

なお、コライダーの設定は「Is Trigger」にチェックを入れています。

そして、以下のスクリプトを丸いオブジェクトにアタッチしておきます。

using UnityEngine;

public class CircleController : MonoBehaviour
{
    void Update()
    {
        // キー操作による移動処理
        if (Input.GetKey(KeyCode.W))
        {
            transform.Translate(0, 0.02f, 0);
        }
        else if (Input.GetKey(KeyCode.S))
        {
            transform.Translate(0, -0.02f, 0);
        }
        else if (Input.GetKey(KeyCode.D))
        {
            transform.Translate(0.02f, 0, 0);
        }
        else if (Input.GetKey(KeyCode.A))
        {
            transform.Translate(-0.02f, 0, 0);
        }
    }

    // 当たり判定のあった場合の処理
    void OnTriggerEnter2D(Collider2D collision)
    {
        Destroy(collision.gameObject);  // 相手のオブジェクトを破壊する
    }
}

27行目でオブジェクトと衝突した際に呼び出すOnTriggerメソッドを定義していて、その中で相手のオブジェクトを破壊するDestroyメソッドを記述しています。

これでゲームを実行してみると、

丸いオブジェクトを動かして、三角と四角のオブジェクトに触れると、両方のオブジェクトとも消えているのが分かります。

次に、四角のオブジェクトの全てのLayerに「Square」という新しいLayerを作り設定します。

そして、メニューバーの「Edit」の中にある「Project Settings…」を開きます。

今回は2Dゲームなので、左側の項目から「Physics 2D」を選択します。

「Layer Collision Matrix」を開くと、それぞれのLayer毎の衝突判定の有無を決める設定が表示されます。

ここで「Default」「Square」のLayerのオブジェクトが衝突しても判定しないようにしたいので、以下のようにお互いの交点となる場所のチェックを外しておきます。

これでもう一度ゲームを実行してみると、

四角いオブジェクトと当たっても、衝突判定が起きずオブジェクトが消えなくなりました。

なお、3Dゲームの場合は、Project Settingsの中の「Physics」にある「Settings」を選択して、さらに「Shared」の中の「Layer Collision Matrix」を開くと同じように衝突判定の有無を設定できます。

Raycastによる衝突判定をLayer毎に変更する

Raycastメソッドを使ってオブジェクトに対して衝突判定を行う際にも、特定のLayerのオブジェクトには衝突させないことができます。

ここでは、3Dゲームでキューブと球体のオブジェクトを2種類配置して、キューブのオブジェクトをマウスでクリックすると消えて、球体のオブジェクトをマウスでクリックしても消えないという処理を作ってみます。

まず、ゲーム内に配置したキューブと球体のオブジェクトに対して、先ほどと同様にコライダーコンポーネントを紐づけておきます。

そして、空のオブジェクトを一つ作成して、以下のスクリプトをアタッチしておきます。

using UnityEngine;

public class Test : MonoBehaviour
{
    void Update()
    {
        // マウスをクリックした場合の処理
        if (Input.GetMouseButton(0))
        {
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);    // カメラからマウスカーソルの位置に向かうRay
            RaycastHit hit; // 当たったオブジェクトの情報
            // Rayを飛ばして当たり判定を検知
            if (Physics.Raycast(ray, out hit))
            {
                Destroy(hit.collider.gameObject);   // 当たったオブジェクトを破壊する
            }
        }
    }
}

マウスをクリックした場合の処理の中で、13行目でRaycastメソッドを使ってマウスでクリックした場所にあるオブジェクトの情報を取得して、そのオブジェクトをDestroyメソッドで破壊する処理を記述しています。

これでゲームを実行してみると、

マウスでオブジェクトをクリックすると、どちらのオブジェクトも消えているのが分かります。

次に、キューブのオブジェクトのLayer設定だけを「Ignore Raycast」に変更してみましょう。

この「Ignore Raycast」は、Unity側で初めから設定されているBuiltin Layerのひとつで、Raycastによる衝突判定を行わないように働きます。

ゲームを実行すると、

キューブのオブジェクトだけマウスでクリックしても、消えないようになりました。

なお、この「Ignore Raycast」のLayerを使わなくても、Raycastメソッドの引数でレイヤーマスクを指定することで、衝突判定を行わないようにすることもできます。

例えば、キューブのオブジェクトのLayer設定として、「Cube」というLayerを新しく作って設定してみます。

そして、スクリプト内で以下のように記述してあげます。

using UnityEngine;

public class Test : MonoBehaviour
{
    void Update()
    {
        // マウスをクリックした場合の処理
        if (Input.GetMouseButton(0))
        {
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);    // カメラからマウスカーソルの位置に向かうRay
            RaycastHit hit; // 当たったオブジェクトの情報
            int layerMask = ~(1 << 3);  // レイヤーマスクを作成
            // Rayを飛ばして当たり判定を検知
            if (Physics.Raycast(ray, out hit, Mathf.Infinity, layerMask))
            {
                Destroy(hit.collider.gameObject);   // 当たったオブジェクトを破壊する
            }
        }
    }
}

14行目のRaycastメソッドの第4引数で、int型の「layerMask」変数を使ってCubeのLayerの番号である「3」のみを除外したレイヤーマスクを、12行目で以下のように作成しています。

int layerMask = ~(1 << 3);  // レイヤーマスクを作成

ゲームを実行すると、

先ほどと同様に、キューブに対して衝突判定を無くすことができているのが分かります。

カメラによる描画処理をLayer毎に変更する

Layer機能は衝突判定だけでなく、カメラで描画処理する際にも使われます。

ここでは、先ほどと同じようにキューブと球体のオブジェクトをシーン内に配置して、キューブのオブジェクトをカメラで描画しないようにしてみます。

キューブのオブジェクトのLayer設定を、全て「Cube」という新しいLayerを作成して設定しておきます。

次に、ゲームを表示しているCameraオブジェクトを選択して、インスペクターウィンドウのCameraコンポーネントにある「Rendering」「Culling Mask」を設定していきます。

この「Culling Mask」は、カメラで表示するLayerを指定している項目で、デフォルトでは「Everything」で全てのLayerが表示されていますが、この中から「Cube」のLayerだけ外しておきます。

これでゲームを実行してみると、

キューブのオブジェクトだけ描画されなくなっているのが分かります。

まとめ

このページでは、Unityで設定できるLayer機能について、どんなことができるのか、使い方や設定方法をまとめていきましたが、いかがでしたでしょうか?

Layer機能は、オブジェクトの衝突や画面表示において、どのように作用するかを決めるグルーピングの機能になっています。

このLayerを使うことで、特定のオブジェクトとの衝突を起こらなくさせたり、特定のオブジェクトを画面に表示させないといったことができるようになります。

特に、オブジェクトを大量に配置している場合は、一括で簡単に処理を行うことができるため非常に便利です。

最後までお読みいただきまして、ありがとうございました!

コメント