Unity:衝突検出イベントの実装(基本形・拡張形)

Unityでオブジェクトとの接触を検出し、カスタムイベントを実行する実装方法を紹介します。
ここでは、基本形(シンプルにCollider情報のみを渡す)と、拡張形(接触したオブジェクトのタグやレイヤーなどの詳細情報を扱う)の2種類の実装例を示します。
クラス名をSimpleCollisionDetector(基本形)とAdvancedCollisionDetector(拡張形)に分けることで、各実装の違いが明確になります。


1. 基本形:SimpleCollisionDetector

コード例

using UnityEngine;
using UnityEngine.Events;

[RequireComponent(typeof(Collider))]
public class SimpleCollisionDetector : MonoBehaviour
{
    // インスペクター上でイベントリスナーを設定可能な UnityEvent
    [SerializeField] private UnityEvent<Collider> onTriggerStay = new UnityEvent<Collider>();

    private void OnTriggerStay(Collider other)
    {
        // 接触中のCollider情報を渡してイベントを実行
        onTriggerStay?.Invoke(other);
    }
}

説明

  • RequireComponent(typeof(Collider))
    → この属性により、SimpleCollisionDetectorがアタッチされたGameObjectには必ずColliderコンポーネントが存在するように強制されます。
  • [SerializeField] private UnityEvent\ onTriggerStay
    → インスペクター上で設定可能なイベントフィールドです。
    new UnityEvent<Collider>() により初期化しているため、null参照のリスクを回避しています。
    → ※ インスペクターからリスナーを設定する場合、Unityのシリアライズシステムが自動でインスタンスを割り当てるため、new は必須ではありませんが、ここでは安全のため使用しています。
  • OnTriggerStay(Collider other)
    → Unityの組み込みイベントメソッドで、他のオブジェクトがCollider内に留まっている間、毎フレーム呼び出されます。
    → 渡されたCollider情報を、登録されたリスナーに渡してイベントを発火します。

2. 拡張形:AdvancedCollisionDetector

拡張形では、接触したオブジェクトの詳細情報(タグ、レイヤーなど)もイベントハンドラに渡すため、専用のデータクラスColliderEventDataを用います。

ColliderEventData クラス

using UnityEngine;
using System;

[Serializable]
public class ColliderEventData
{
    public Collider Collider { get; private set; }
    public string Tag { get; private set; }
    public int Layer { get; private set; }

    public ColliderEventData(Collider collider)
    {
        Collider = collider;
        Tag = collider.tag;
        Layer = collider.gameObject.layer;
    }
}

AdvancedCollisionDetector クラス

using UnityEngine;
using UnityEngine.Events;

[RequireComponent(typeof(Collider))]
public class AdvancedCollisionDetector : MonoBehaviour
{
    // ColliderEventDataを引数に取る UnityEvent を使用
    // ※ インスペクターで設定する場合、Unity のシリアライズシステムが自動でインスタンスを生成するため、必ずしも new キーワードは必須ではありません。
    [SerializeField] private UnityEvent<ColliderEventData> onColliderStay = new UnityEvent<ColliderEventData>();

    private void OnTriggerStay(Collider other)
    {
        // 接触情報の詳細データを生成してイベントを発火
        var eventData = new ColliderEventData(other);
        onColliderStay.Invoke(eventData);
    }
}

説明

  • [SerializeField] private UnityEvent\ onColliderStay
    → AdvancedCollisionDetectorでは、接触時に詳細な情報(タグ、レイヤーなど)をまとめたColliderEventData型のイベントを用います。
  • OnTriggerStay(Collider other)
    → 接触したオブジェクトのCollider情報を元にColliderEventDataを生成し、onColliderStayイベントに渡して実行します。
  • new キーワードについて
    → インスペクター上でイベントリスナーを設定する場合、Unityは自動でインスタンスを生成するため、new キーワードは必ずしも必要ありません。
    → しかし、コードから直接イベントリスナーを追加する場合や、実行時の安全性を確保するためには、new キーワードで初期化しておくと安心です。

3. イベントリスナーの設定例

Detector側で発行したイベントを受け取り、処理するリスナーを作成します。ここでは、基本形と拡張形それぞれに対応したリスナーの例を示します。

3.1 基本形用リスナー: BasicCollisionListener

using UnityEngine;

public class BasicCollisionListener : MonoBehaviour
{
    // SimpleCollisionDetectorで発火するイベントを受け取り、Collider情報を処理するメソッド
    public void OnTriggerStayDetected(Collider collider)
    {
        Debug.Log($"[基本形] オブジェクトとの接触を検知しました: {collider.gameObject.name}, タグ: {collider.tag}, レイヤー: {collider.gameObject.layer}");
    }
}

3.2 拡張形用リスナー: AdvancedCollisionListener

using UnityEngine;

public class AdvancedCollisionListener : MonoBehaviour
{
    // AdvancedCollisionDetectorで発火するイベントを受け取り、詳細な接触情報を処理するメソッド
    public void OnStayDetected(ColliderEventData eventData)
    {
        Debug.Log($"[拡張形] オブジェクトとの接触を検知しました: {eventData.Collider.gameObject.name}, タグ: {eventData.Tag}, レイヤー: {eventData.Layer}");
    }
}

Unityエディタでの接続手順(共通)

  1. Colliderコンポーネントの確認
    • GameObjectにSimpleCollisionDetectorまたはAdvancedCollisionDetectorがアタッチされ、Colliderが存在し、Is Trigger が有効になっていることを確認します.
  1. リスナーの追加
    • シーン内の別のGameObjectに BasicCollisionListener または AdvancedCollisionListener コンポーネントをアタッチします。
    • 対象のDetectorコンポーネントのイベントフィールド(基本形なら onTriggerStay、拡張形なら onColliderStay)の「+」ボタンをクリックし、リスナーとして該当するGameObjectを追加します。
    • ドロップダウンから、対応するリスナーのメソッド(基本形の場合は BasicCollisionListener -> OnTriggerStayDetected(Collider)、拡張形の場合は AdvancedCollisionListener -> OnStayDetected(ColliderEventData))を選択します。
  1. 実行確認
    • シーンを再生し、対象オブジェクトがDetectorのCollider内に入ると、各イベントが発行され対応するリスナーのメソッドが呼び出され、Consoleにログが出力されます。

次のようなシーン構成でテストができます

  • Cube 1: 衝突検出用のスクリプト(SimpleCollisionDetector または AdvancedCollisionDetector)をアタッチし、Collider(Is Trigger有効の場合も)と必要ならRigidbodyを追加します。
  • Cube 2: 衝突対象として、Collider(必要ならRigidbodyを追加)を持たせ、Cube 1との衝突を発生させます。
  • 空のGameObject: イベントリスナー(BasicCollisionListener または AdvancedCollisionListener)をアタッチして、衝突イベントの通知を受け取る役割にします。

このような構成で、Cube 1とCube 2が実際に衝突した際に、空のGameObjectにアタッチされたリスナーがイベントを受信して処理できるかどうかを確認できます。これにより、基本的な衝突検出の動作やイベント連携をテストできるので、学習やデバッグにとても有用です。


まとめ

  • SimpleCollisionDetector(基本形)
    • イベント名: onTriggerStay
    • 引数: Collider型
    • シンプルな実装で、基本的な接触検出とイベント発行が可能。
  • AdvancedCollisionDetector(拡張形)
    • イベント名: onColliderStay
    • 引数: 詳細情報を含む ColliderEventData型
    • 接触時にオブジェクトのタグやレイヤーなどの情報も扱い、柔軟なイベント処理が実現可能。
  • new キーワードについて
    • インスペクター上での設定時、Unityは自動でイベントフィールドにインスタンスを割り当てるため必ずしもnewは必要ありません。
    • ただし、コードから直接リスナーを追加する場合や実行時の安全性を考慮する場合は、new キーワードで初期化することを推奨します。

この資料では、各クラスの役割や接続方法、さらにキャプチャ例の挿入位置も示しました。初学者でも各実装の違いと用途が理解しやすく、プロジェクトの要件に合わせた適切な選択ができるようになります。

Unity,イベント

Posted by hidepon