イベントの仕組みと活用方法
本資料では、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
ディスカッション
コメント一覧
まだ、コメントがありません