(この記事の使用環境: Unity 2018.1.0b9 Personal、Visual Studio Community 2017, Windows10)

前置き

Unity公式チュートリアルや市販の教本などで、オブジェクト同士の衝突判定条件に Tag を使っているケースがたくさんあります。
しかし、そのような場合は(基本的には) Tag (だけ)ではなくて Layer を使う(併用する)ほうがラクチンだなと、ゲーム作りをしていてあらためて感じました。また、各ゲームオブジェクトに適切にLayerを設定してやることで、CameraLightingRaycast 等の対象を限定することもできます。
そのあたりを簡単にまとめておきたいなと思いまして。

ゲームオブジェクトにLayerを設定しよう

まずは何はともあれゲームオブジェクトにLayer設定をします。

このゲームを例にして設定してみる

以下、unityroom に公開したこちらのゲームを対象とした設定例を紹介します。
png

Layerの設定対象

設定対象は、まずは「形があって、ゲーム画面内に登場する」ゲームオブジェクトとプレハブのほぼすべてと考えておけばいいのかなと。(そのうえで、明らかに設定不要なものは除外する)

【例】Layer設定対象とするゲームオブジェクトおよびプレハブはこんな感じ。
Player(プレイヤーが操作する機体)
Player Bolt(Playerの発射する弾)
Enemy Ship, Asteroid(敵機体、障害物)
Enemy Bolt(Enemy Shipが発射する弾)
Item(各種)(Playerが入手することのできるアイテム)
Boundary(ゲームの領域。処理負荷軽減のため、各ゲームオブジェクトはこの領域外に出るときに破壊されるようにスクリプトで設定している)
UI(各種UI要素。UIレイヤーは自動的に設定される)

今回は背景の一枚絵や爆発のプレハブにはLayer設定していません。これらは今回はほかのゲームオブジェクトと衝突させないので、特に設定不要と考えました。爆発を派手にしたり他のオブジェクトと衝突させたいような場合には適切に設定するといいかも。

作成するLayerを決める

まずは作成するLayerを考えます。その際、Layer間の衝突有無をどうするかあらかじめ考えておくとよさそう。
【例】作成するLayer名と対応するゲームオブジェクト(カッコ内)、衝突対象のレイヤーはこんな感じ。
Player(Player):Enemy, EnemyShot, Itemと衝突
PlayerShot(Player Bolt):Enemy, Boundaryと衝突
Enemy(Enemy Ship, Asteroid):Player, PlayerShot, Boundaryと衝突
EnemyShot(Enemy Bolt):Player, Boundaryと衝突
Item(各種Item):Player, Boundaryと衝突
Boundary(Boundary):PlayerShot, Enemy, Item, EnemyShotと衝突
UI(各種UI要素):どれとも衝突しない

Layerを作成する

Layerは Edit > Project Srttings > Tags and Layers から作成します。
png

ゲームオブジェクトとプレハブにLayerを設定する

Layerを作成したら、各ゲームオブジェクト(とプレハブ)の最上位でLayer設定し、子オブジェクトにも反映させます。
png

Layer間の衝突有無を設定する

Edit > Project Settings > Physics から、インスペクターの Layer Collision Matrix で Layer間の衝突有無を設定します。
Layer Collision Matrix は初期状態ではすべてチェックが入っていますが、見た目の分かりやすさのため、いったん全部外してから、必要な箇所にだけチェックするようにしてみました。このほうが設定ミスを減らせそうかなと。
png

このようにLayerの設定をしておくことで、「PlayerとPlayerShotは衝突しない」「ItemはPlayerだけが入手できる」などというような判定条件をいちいちスクリプト内に書き込む必要が少なくなるので、コードがシンプルになりミスも減らせると思います。

適切にLayerの設定をすることは処理負荷軽減にもつながるようです。
参考:Unity - 物理演算のベストプラクティス

Cameraが映す対象をLayerで限定する

Cameraが映す対象を Culling Mask から Layer で指定できます。チェックを外せばそのCameraには映らなくなります。複数のCameraを使ってそれぞれに映し出す対象を変えるなどの使い方があるようです。
png

Lightingの対象もLayerごとに限定できる

同様に、Light の光を受ける対象も CullingMask で設定できます。Lighting は結構処理負荷が大きいようなので、対象を絞り込むと負荷軽減になるかもしれません。
png

Raycastの対象もLayerで限定できる

Raycastで検出する対象もLayerで限定できます。
こちらの記事が詳しいです。丸投げすまんです。

まとめ

ということで、Layerを適切に設定するとけっこう役に立つぞ、というお話でした。
特に衝突判定に関しては、ゲームオブジェクトにTagをつけてスクリプト内にさまざまな条件を書くよりかなり簡単になり、ミスも減らせると思います。

参考資料



今回は以上です。