イベントの仕組みと活用方法
本資料では、Unityにおけるイベントの仕組みとその活用方法について解説します。イベントを正しく理解し活用することで、コードの拡張性や保守性を高めることができます。
イベントとは
イベントとは、特定の「きっかけ」が発生したときに、あらかじめ登録されたメソッド(イベントハンドラ)が実行される仕組みのことです。
イベントのきっかけとなるもの
- ボタンが押された
 - キー入力があった
 - タイマーで時間が経過した
 - オブジェクト同士が衝突した
 - その他のカスタムイベント
 
きっかけから実行したい処理
- 計算処理
 - 得点の増加
 - ライフの減少
 - ゲームオーバー処理
 - 画面効果の発動 など
 
イベントを使わない実装方法と課題
シンプルな実装例
例えば、スペースキーの押下を「敵にやられた」と見立てて、以下のように実装します。
void Update()
{
    if (Input.GetKeyDown(KeyCode.Space))
    {
        Debug.Log("ライフが減った");
    }
}
この程度の処理であれば、特に問題なく実装できます。
機能追加による複雑化
しかし、機能追加に伴い処理が増えていくと、Updateメソッド内のifブロックが肥大化し、可読性や保守性が低下します。
void Update()
{
    if (Input.GetKeyDown(KeyCode.Space))
    {
        Debug.Log("ライフが減った");
        Debug.Log("もし、ライフが0ならゲームオーバー");
        Debug.Log("自分を消滅させる");
    }
}
更なる要望による問題点
追加の要望:
- 派手な爆発アニメーションを実行したい
 - タイマーを一時停止したい
 - 背景を点滅させたい
 - 全ての敵のスピードを一時的に遅くしたい
 
これらを実装すると、以下の問題が発生します。
Updateメソッドが肥大化し、読みづらくなる- 他クラスのメソッド呼び出しが増え、依存関係が複雑になる
 - オブジェクト指向の設計原則に反し、拡張や修正が困難になる
 
イベントの活用
上記の問題を解決するために、イベントの仕組みを導入します。
4.1 基本的なイベントの実装
UnityEventを使用して、イベントを定義します。
using UnityEngine;
using UnityEngine.Events;
public class EventTrigger : MonoBehaviour
{
    public UnityEvent unityEvent;
    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            unityEvent.Invoke();
        }
    }
}
4.2 イベントハンドラの登録方法
4.2.1 インスペクタでの登録
EventTriggerスクリプトをゲームオブジェクトにアタッチします。- インスペクタで
UnityEventに実行したいメソッドを登録します。 
Unity UIのボタンイベントと同様の手順で登録可能です。
4.2.2 コードでの登録
using UnityEngine;
public class UIController : MonoBehaviour
{
    public EventTrigger eventTrigger;
    void Awake()
    {
        eventTrigger.unityEvent.AddListener(ShowLife);
    }
    public void ShowLife()
    {
        Debug.Log("ライフの表示を更新");
    }
}
UIControllerスクリプトを適切なゲームオブジェクト(例:Canvas)にアタッチします。eventTriggerに対象のEventTriggerオブジェクトをアサインします。
実行結果
ライフの表示を更新
4.3 引数を持つイベント
引数付きのイベントを使用する場合、UnityEvent<T0, T1, T2, T3>を用います(最大4つの引数まで)。
イベントの宣言と呼び出し
public UnityEvent<string, int> unityEvent;
void Update()
{
    if (Input.GetKeyDown(KeyCode.Space))
    {
        unityEvent.Invoke("スペース", 5);
    }
}
イベントハンドラの実装
public void ShowLife(string msg, int data)
{
    Debug.Log($"{msg} と {data}を受け取りました");
}
実行結果
スペース と 5を受け取りました
4.4 動的に生成されるオブジェクトでのイベント活用
Prefabから生成されるエネミーに対して、イベントを活用する例です。
using UnityEngine;
public class Enemy : MonoBehaviour
{
    EventTrigger eventTrigger;
    int speed;
    private void OnEnable()
    {
        eventTrigger = GameObject.Find("EventSystem").GetComponent<EventTrigger>();
        eventTrigger.unityEvent.AddListener(DecreaseSpeed);
    }
    private void OnDisable()
    {
        eventTrigger.unityEvent.RemoveListener(DecreaseSpeed);
    }
    public void DecreaseSpeed()
    {
        speed--;
    }
}
- エネミーが生成されるたびに、イベントにハンドラを登録します。
 - エネミーが破棄されるときに、イベントからハンドラを解除します。
 
高度なイベント処理
さらに複雑な処理や条件分岐が必要な場合、Reactive Extensionsを利用することができます。
例:UniRxの活用
- 最初の一回だけ特定の処理を行う
 - 特定の条件下で一度だけイベントを発火する
 - 複数のイベントを統合して処理する
 
参考リンク
UniRx勉強会〜実用例を見ながら〜 #C# – Qiita





ディスカッション
コメント一覧
まだ、コメントがありません