UnityEvent を使ったイベント登録入門チュートリアル – EventDispatcher と EventReceiver の連携(int 型引数付き/コード登録版)

この資料では、初めは単なるメソッド定義から始め、シーン開始時に呼び出す方法、そして最終的に UnityEvent を利用して、異なる GameObject にアタッチされたスクリプト間で int 型の引数付きイベントをコード内で登録・発行する手順を解説します。
使用するスクリプトと GameObject は以下の通りです。

  • EventDispatcher.cs
    (イベント発行側のスクリプト。コード内でリスナーを登録)
    → アタッチする GameObject の名称:EventSender
  • EventReceiver.cs
    (イベント受信側のスクリプト。発行されたイベントを受け取る)
    → アタッチする GameObject の名称:EventListener

1. 初めに:単なるメソッドの定義(引数なし)

まずは、DisplayGreeting() というメソッドを定義しただけの状態です。この段階ではメソッドは存在するものの、どこからも呼び出されないため実行(発行)されません。

using UnityEngine;

public class EventDispatcher : MonoBehaviour
{
    // 「こんにちは、世界!」を表示するメソッド(定義のみ)
    void DisplayGreeting()
    {
        Debug.Log("こんにちは、世界!");
    }
}

ポイント
この状態では、単にメソッドが存在するだけで、実行(発行)されることはありません。


2. Start() からのメソッド呼び出し(引数なし)

次に、Start() メソッド内で DisplayGreeting() を呼び出すようにコードを変更します。これにより、シーン開始時にメソッドが自動的に実行され、コンソールに「こんにちは、世界!」が出力されます。

using UnityEngine;

public class EventDispatcher : MonoBehaviour
{
    void Start()
    {
        // シーン開始時に DisplayGreeting() を呼び出す
        DisplayGreeting();
    }

    void DisplayGreeting()
    {
        Debug.Log("こんにちは、世界!");
    }
}

ポイント

  • Start() は MonoBehaviour の初期化メソッドです。
  • シーン開始と同時に DisplayGreeting() が実行され、コンソールにメッセージが表示されます。

3. int 型引数を渡すためのコード更新(コードでのリスナー登録)

ここから、int 型の引数を渡すために、イベントの型を UnityEvent<int> に変更し、さらにリスナーの登録をインスペクターではなくコード内で行います。
また、Start() 内でイベント発行時に数値(例として 100)を渡します。

using UnityEngine;
using UnityEngine.Events;

public class EventDispatcher : MonoBehaviour
{
    // UnityEvent<int> 型のイベント(int 型引数付き)
    public UnityEvent<int> greetingEvent;

    void Awake()
    {
        // イベントが未初期化の場合は初期化する
        if (greetingEvent == null)
            greetingEvent = new UnityEvent<int>();
    }

    void Start()
    {
        // コードでリスナーを登録
        // 1. 自分自身のメソッドをリスナーとして登録
        greetingEvent.AddListener(DisplayGreetingWithInt);

        // 2. "EventListener" という名前の GameObject から EventReceiver コンポーネントを取得してリスナーとして登録
        EventReceiver receiver = GameObject.Find("EventListener")?.GetComponent<EventReceiver>();
        if (receiver != null)
        {
            greetingEvent.AddListener(receiver.DisplayGreetingWithInt);
        }
        else
        {
            Debug.LogWarning("EventListener が見つからないか、EventReceiver コンポーネントがアタッチされていません。");
        }

        // シーン開始時に、登録された全てのメソッドへ int 型引数 100 を渡してイベントを発行する
        greetingEvent.Invoke(100);
    }

    // int 型引数付きのメソッド
    public void DisplayGreetingWithInt(int value)
    {
        Debug.Log("EventSender より: " + value + " のメッセージ こんにちは、世界!");
    }
}

ポイント

  • イベントの型を UnityEvent<int> に変更することで、int 型の引数を渡せるようになります。
  • greetingEvent.AddListener(…) を使い、インスペクターを介さずにリスナーをコードで登録します。
  • GameObject.Find を用いて、別の GameObject(EventListener)から EventReceiver コンポーネントを取得し、リスナーに追加しています。

4. 別の GameObject のスクリプトのメソッドも実行する(int 型引数付き/コード登録版)

次に、別の GameObject にアタッチされた EventReceiver.cs を、int 型の引数を受け取るように作成します。
こちらはコード内でイベントリスナーとして登録されるため、インスペクターでの設定は不要です。

EventReceiver.cs の作成

using UnityEngine;

public class EventReceiver : MonoBehaviour
{
    // int 型引数を受け取るメソッド
    public void DisplayGreetingWithInt(int value)
    {
        Debug.Log("EventListener よりご挨拶: " + value + " のメッセージ こんにちは、世界!");
    }
}

ポイント

  • このスクリプトは、EventListener という名前の GameObject にアタッチしてください。
  • コード内で EventDispatcher がリスナーとして登録するため、インスペクターでの設定は不要です。

実行結果


5. まとめ

  1. 単なるメソッド定義(引数なし)
    • まずは DisplayGreeting() というメソッドを定義するだけの状態。
  2. Start() から呼び出す(引数なし)
    • シーン開始時に直接 DisplayGreeting() を実行してメッセージを出力する方法を学習。
  3. int 型引数を渡すためのコード更新(コード登録版)
    • イベントの型を UnityEvent<int> に変更し、コード内で AddListener() を使って自分自身および別の GameObject のメソッドを登録。
    • Invoke(100) により、数値 100 を引数として渡す方法を習得。
  4. 他の GameObject のスクリプトのメソッドも実行(int 型引数付き/コード登録版)
    • EventSenderEventListener の双方で、int 型引数付きのメソッド(DisplayGreetingWithInt)をコード内で登録し、シーン再生時に連携して処理を実行する仕組みが実現できます。

この手順を通して、UnityEvent の基本的な使い方に加え、コード内でのイベントリスナー登録と、引数付きのイベント発行・受信の方法を理解し、実際のプロジェクトに柔軟に応用できるようになります。

以下は、EventReceiver 側でイベント登録を行う方法のポイントをまとめた内容です。


EventReceiver 側でイベント登録する方法のまとめ

  1. EventDispatcher への参照取得
    • インスペクターで設定する方法:
      • EventReceiver のスクリプト内に、EventDispatcher 型の public フィールドを用意して、エディタ上で参照を設定する。
    • コードで自動取得する方法:
      • GameObject.Find("EventSender") などを利用して、発行側の GameObject からコンポーネントを取得する。
  2. リスナーの登録
    • EventDispatcher 側で定義されている UnityEvent(ここでは UnityEvent<int>)に対して、EventReceiver 側の処理用メソッド(例: DisplayGreetingWithInt(int))を AddListener() を使って登録する。
    • これにより、発行側のイベントが実行された際に、自動的に EventReceiver 側のメソッドが呼び出され、引数として渡された値を受け取る。
  3. リスナーの解除
    • オブジェクト破棄時(例えば OnDestroy() 内)に、登録したリスナーを RemoveListener() で解除する。
    • これにより、不要な参照が残らず、メモリリークや予期せぬ挙動を防ぐことができる。

まとめサンプルコード例

以下は、上記のポイントを反映したサンプルコードです。

using UnityEngine;

public class EventReceiver : MonoBehaviour
{
    // EventDispatcher への参照(インスペクターで設定、もしくはコードで取得)
    public EventDispatcher dispatcher;

    void Start()
    {
        // コードで自動取得する場合
        if (dispatcher == null)
        {
            dispatcher = GameObject.Find("EventSender")?.GetComponent<EventDispatcher>();
        }

        if (dispatcher != null && dispatcher.greetingEvent != null)
        {
            // イベント発行側の UnityEvent<int> に、自身のメソッドをリスナーとして登録する
            dispatcher.greetingEvent.AddListener(DisplayGreetingWithInt);
        }
        else
        {
            Debug.LogWarning("EventDispatcher の参照が見つからないか、greetingEvent が初期化されていません。");
        }
    }

    // int 型引数を受け取るリスナーメソッド
    public void DisplayGreetingWithInt(int value)
    {
        Debug.Log("EventListener よりご挨拶: " + value + " のメッセージ こんにちは、世界!");
    }

    void OnDestroy()
    {
        // オブジェクト破棄時にリスナーを解除する
        if (dispatcher != null && dispatcher.greetingEvent != null)
        {
            dispatcher.greetingEvent.RemoveListener(DisplayGreetingWithInt);
        }
    }
}

実行結果


この方法により、EventReceiver 側で自らイベント登録を行い、発行側から送られるイベントを受信・処理できるようになります。これにより、システム内の責務を分散し、柔軟なイベント連携が実現可能です。

Unity,イベント

Posted by hidepon