1つのゲームオブジェクトに複数のコライダーがアタッチされている場合の当たり判定

2023年9月15日

2つ以上のコライダーがアタッチされている場合、複数の当たりイベントが発生します
その様子と、1つのイベントとして処理する方法を見ていきます

問題のシーン

Playerゲームオブジェクトには、2つのコライダー(BoxCollider2DとCircleCollider2D)がアタッチされています
また、Rigidbody2Dもアタッチされています
Enemyゲームオブジェクトには、1つのコライダー(BoxCollider2D)がアタッチされています
コライダーのIsTriggerプロパティにチェックが入っています

1つのゲームオブジェクトに2つのコライダーがアタッチされているシーン

Playerのスクリプト

using UnityEngine;

public class PlayerController : MonoBehaviour
{
    void OnTriggerEnter2D(Collider2D collision)
    {
        Debug.Log("敵と当たった");
    }
}

テスト(デバッグ)

Unityで部分的なテストをする場合、必ずしも移動用のコードを必要としません
今回は、実行後にSceneウィンドウで、移動アイコンを選択し、X軸矢印(赤色)をマウスで摘んで(ドラッグして)移動させることができます。Enemyを近づけて接触を試すことができます。

テストの様子

結果

Consoleウィンドウで結果の表示を見てみると、2回当たり判定がなされていることがわかります

敵と当たった
敵と当たった

試しにコライダーを1つにしてみると

では、CircleColliderを無効(チェックボックスを外す)にして再度試してみると

テストの様子

結果

はい、1回だけになりましたね

敵と当たった

では、2つのコライダーをアタッチした状態で1回の接触判定にするにはどうすればいいでしょうか?
「コライダーを1つにする」という選択はなしということで。2つにするのは意味があるでしょう。

1回だけ当たり判定がなされるように対応

ここでは、1つの解決策を提示します。これしかないわけではありませんが、参考にしていただければと思います。

接触用のコライダーを別のゲームオブジェクトにアタッチする

別といっても、自身の子ゲームオブジェクトにします
名前をHitColliderとして、そのゲームオブジェクトにBoxCollider2Dを移動します

親オブジェクトからBoxCollider2Dを移動します

子オブジェクトは次のようになります

子オブジェクトにアタッチするスクリプト

イベントを使っています
トリガーイベント発生時に、OnHitに登録されたメソッドが実行される設定になります

using UnityEngine;
using UnityEngine.Events;

public class ColCheck : MonoBehaviour
{
    public UnityEvent OnHit;

    void OnTriggerEnter2D(Collider2D collision)
    {
        OnHit.Invoke();
    }
}

親オブジェクトにアタッチするスクリプト

あらかじめ、実行されるメソッドを用意しておきます

using UnityEngine;

public class PlayerController : MonoBehaviour
{
    public void TriggerCheck()
    {
        Debug.Log("敵と当たった");
    }
}

イベントの登録

子オブジェクトのインスペクターを確認してみましょう
スクリプトにイベントが登録できるような場所が現れましたよね
イ当たり判定(OnTrigger)が発生したときに実行されるメソッドを登録しておきます

Player(PlayerContoller)のところには、Playerゲームオブジェクトをドラッグ&ドロップします
PlayerController .TriggerCheckは(キャプチャではすでに選択済みです)PlayerControllerを選択後、TriggerCheckメソッドを選択しています

実行結果

敵と当たった

コード解説

子オブジェクトのコード

このコードは、Unityゲームエンジンで使用するためのC#スクリプトです。このスクリプトは、オブジェクトが2Dコライダー(Collider2D)に触れる(衝突する)瞬間に特定のアクションを実行するためのコンポーネントを定義しています。

以下は、このコードの主要な要素とその説明です:

using UnityEngine;
using UnityEngine.Events;

UnityEngine および UnityEngine.Events ネームスペースをインポートしています。これらのネームスペースには、Unityのクラスと機能にアクセスするための必要なクラスやメソッドが含まれています。

public class ColCheck : MonoBehaviour

ColCheck という名前のC#クラスを宣言しています。このクラスは MonoBehaviour クラスを継承しています。MonoBehaviour は、Unityのゲームオブジェクトにアタッチできるスクリプトの基本クラスです。

public UnityEvent OnHit;

OnHit という名前のパブリックなフィールドを宣言しています。このフィールドの型は UnityEvent です。UnityEvent は、Unityのイベントを表現するためのクラスであり、イベントリスナーとして機能します。

void OnTriggerEnter2D(Collider2D collision)

OnTriggerEnter2D メソッドを宣言しています。このメソッドは、オブジェクトが2Dコライダーに触れた瞬間に呼び出されるUnityのコライダーイベントです。このメソッドは、引数として Collider2D 型の変数 collision を受け取ります。

OnHit.Invoke();

OnHit イベントを呼び出しています。つまり、このスクリプトがアタッチされたゲームオブジェクトが2Dコライダーに触れると、OnHit イベントがトリガーされ、イベントに登録されたリスナー(別のスクリプトやゲームオブジェクト)が実行されます。

このスクリプトを使用すると、特定のゲームオブジェクトが2Dコライダーに触れたときに、他のゲームオブジェクトやスクリプトによって定義されたアクションが実行されるようになります。たとえば、ゲーム内のアイテムがプレイヤーに拾われたときに、そのアイテムの消去などのアクションを実行するのに役立つでしょう。

親オブジェクトのコード

このコードは、Unityゲームエンジンでプレイヤーキャラクターの挙動を制御するためのC#スクリプトです。以下でコードの主要な部分を説明します。

using UnityEngine;

この行は、Unityエンジンの機能を使用できるようにUnityの名前空間をインクルードしています。Unityのクラスやメソッドを使用するためには、この行が必要です。

public class PlayerController : MonoBehaviour

これはクラスの宣言です。PlayerControllerというクラスを宣言しており、MonoBehaviourクラスを継承しています。MonoBehaviourは、Unityスクリプトの基本クラスで、これを継承することでUnityのライフサイクルイベントに対応できます。

public void TriggerCheck(): この行は、TriggerCheckという公開された(他のスクリプトからアクセス可能な)メソッドを宣言しています。このメソッドは戻り値がvoidで、引数を持たず、何も返さないことを示しています。

{ Debug.Log("敵と当たった"); }

メソッドの本体です。この中で、Debug.Log関数を使用して文字列 “敵と当たった" をコンソールに出力します。つまり、このメソッドが呼び出されたときに、このメッセージがコンソールに表示されます。

このスクリプトは、ゲーム内のプレイヤーキャラクターが何らかのトリガー条件を満たした場合に、TriggerCheckメソッドが呼び出されて “敵と当たった" というメッセージがコンソールに表示される役割を果たします。このスクリプトをプレイヤーキャラクターにアタッチすることで、プレイヤーと敵の接触を検出し、必要な処理を実行することができます。

Unity

Posted by hidepon