
地形に衝突したら爆発させるみたいなことをしてみたい!
本記事の内容
・当たり判定を設定するLayerの設定方法
・2Dゲームで使うColliderの形状の種類
・接触しない判定の作り方(キネマティック)




物理演算ってなに?
という方は以下の記事を見てください!


当たり判定を自在に設定して複雑なゲームを作ろう!
壁を貫通する弾と貫通しない弾
アクションゲームなどでは、当たり判定を正しく設定しないと、理不尽なゲームになってしまいます。
当たっていないと思っていたら当たったり、味方の弾に当たって死亡したり・・・。
そうならないために、Unityの標準のLayerの機能を使って、当たり判定を自在に操りましょう。
この例では、壁を貫通するビーム武器と、壁を貫通しない実弾武器という二種類の弾を作成するためのレイヤー機能について詳しく解説します。
オブジェクトの準備
まず、以下のオブジェクトをシーンに作成します。この記事では解説のため、Unity標準の図形を使います。
- 壁(緑色の四角形)
- 実弾(黄色の円)
- ビーム(青色の円)


そして、それぞれにRigidBody2Dと、Colliderを設定します。Rigidbody2D、Colliderの設定方法は下記の記事で解説しているので、やり方が分からなければ参考にしてください。


適当にRigidbody2DとColliderを設定しました。


レイヤーの設定
今回は、青色の弾はビーム武器とみなすので、壁を貫通するものとします。ここで必要になるのが、レイヤーの設定です。まずは、以下の通りレイヤーを設定してみます。
レイヤーを設定するには、レイヤーを作成する必要があります。タグと同じですね。
レイヤーを作るには、インスペクタウィンドウを開いて、「レイヤーを追加」を実行します。


今回は、「Wall」、「Bullet」、「Beam」という3つのレイヤーを作ってみました。


先程のオブジェクトに、レイヤーを設定してみましょう。
ゲームオブジェクト | 設定するLayer |
---|---|
Wall(緑の壁) | Wall |
実弾(黄色い球) | Bullet |
ビーム(青色の球) | Beam |
レイヤー同士の干渉の設定
次にレイヤー同士の干渉の設定をします。この設定はプロジェクト共通の内容のため、プロジェクト設定から行います。
上部のウィンドウの 編集 >プロジェクト設定 を選択し、「2D物理」を開きましょう。


このように、各レイヤー間で衝突を管理するマトリクスが表示されます。
デフォルトだとすべてにチェックがついていますが、今回はBeamは壁を貫通するので、BeamとWallの接点のチェックを外します。


これで設定は完了です。
実際に確かめてみる
黄色の実弾だけ壁に当たるようになっているか確認してみましょう。
実弾を発射するスクリプトを作成して、実弾(黄色の丸)とビーム(青色の丸)にアタッチします。
ChatGPTへのプロンプト
弾にアタッチするスクリプトで、スペースを押したら右方向にAddForceするスクリプトを作成してください
ChatGPTが作成したスクリプト
using UnityEngine;
public class BulletController : MonoBehaviour
{
// 弾に加える力の大きさ。
public float forceAmount = 500f;
// Rigidbody2Dコンポーネントを格納する変数。
private Rigidbody2D rb2d;
void Start()
{
// ゲーム開始時にRigidbody2Dコンポーネントを取得してrb2dに格納。
rb2d = GetComponent<Rigidbody2D>();
}
void Update()
{
// スペースキーが押されたら力を加える。
if (Input.GetKeyDown(KeyCode.Space))
{
AddForceToBullet();
}
}
void AddForceToBullet()
{
// Rigidbody2Dがアタッチされていることを確認。
if (rb2d != null)
{
// 右方向(Vector2.right)に力を加える。
rb2d.AddForce(Vector2.right * forceAmount);
}
}
}
上記のスクリプトを、実弾とビームの弾両方にアタッチしました。


ビームが壁を貫通することを確認する
同じスクリプトがアタッチされたオブジェクトですが実行してみると以下の通り、青色の弾は壁を貫通しますね。これが当たり判定のレイヤーの設定です。




接触判定はしたいけど、衝突してほしくない場合
コライダーのトリガーを使おう!
ゲームを作成すると、「このエリアにプレイヤーが入ったら、ムービーの再生を行う」など、エリアに入っているかの判定であったり、当たっているかを判定したいけど、ぶつかってほしくないケースがあります。
また、ほかにもドアを開ける処理をする場合、ドアが開いているアニメーションが再生されている途中で、プレイヤーがドアに接触したりすると、ちゃんとドアが開かなくなったりします。
そんな時に使うのが、Colliderの「トリガー」の設定です。
トリガーに設定すると、貫通可能な当たり判定を作ることが出来ます。先程のレイヤー単位での当たり判定の設定はそもそも当たり判定自体を発生させない設定でした。
一方、こちらは当たり判定自体は発生させるものの、衝突をさせないようにする、というものです。
衝突をさせない当たり判定(トリガーにする)の設定方法
設定方法は簡単です。コライダーの「トリガーにする」をOnにするだけです。


設定を実際に確認してみる
例えばプレイヤーが、緑の壁を通り抜けたら赤くする処理を行ってみます。
プレイヤーには、「Player」というタグを設定しました。プレイヤーを白い箱に見立てて、壁を「トリガーにする」の設定をします。


ChatGPTへのプロンプト
2DのUnityのゲームを作成しています。 プレイヤー(タグ名:Player)が通りすぎたら、赤色にオブジェクトの色を変更するスクリプトを作成してください。
using UnityEngine;
public class ChangeColorOnPass : MonoBehaviour
{
// OnTriggerEnter2Dは他のオブジェクトがこのオブジェクトのトリガーに入ったときに呼び出されます。
private void OnTriggerEnter2D(Collider2D collision)
{
// もし衝突したオブジェクトのタグが"Player"なら、色を変更します。
if (collision.CompareTag("Player"))
{
// このオブジェクトのSpriteRendererコンポーネントを取得します。
SpriteRenderer renderer = GetComponent<SpriteRenderer>();
// 色を赤色に変更します。
if (renderer != null)
{
renderer.color = Color.red;
}
}
}
}
このスクリプトを壁にアタッチして実行してみましょう。




このように、ぶつからずとも、接触を検知することが出来ました!
トリガー(衝突させない)にする場合と、そうでない(衝突させる)場合で、スクリプトの書き方が変わります。
トリガーにする場合は、以下の標準メソッド(あらかじめ定義されているメソッド)を使います。OnTriggerEnter2D(Collider2D collision)
トリガーにしない場合は、以下の標準メソッド(あらかじめ定義されているメソッド)を使います。OnCollisionEnter2D(Collider2D collision)
この設定が一致していないと動作しないので、気をつけましょう!ChatGPTに指示する際は、この前提を教えてあげないと欲しいスクリプトが出力されません。
まとめ
何と何を接触させるか、接触はさせるが衝突はさせないための制御方法についての解説記事でした。
当たり判定を極めて、素敵なゲーム制作ライフを!
コメント