【Unity】Unityでオブザーバーデザインパターンを当てはめてみる

Unityにおけるオブザーバーパターンは、イベントシステムやイベントリスナーを使用して、オブジェクト間の通知と通信を実現するためのデザインパターンです。オブザーバーパターンは、一つのオブジェクト(サブジェクトまたはオブザーバーと呼ばれる)が他の複数のオブジェクト(オブザーバーまたはリスナーと呼ばれる)に変更やイベントの通知を行うことを可能にします。

Unityでは、イベントシステムを使用してオブザーバーパターンを実装することができます。イベントシステムは、イベントを発生させるオブジェクト(パブリッシャー)とイベントを受け取るオブジェクト(サブスクライバー)の間のメッセージングを簡単に行うことができます。

具体的な実装方法は以下のような手順で行われます:

  1. イベントクラスの作成: イベントのデータを保持するためのクラスを作成します。例えば、プレイヤーがダメージを受けたことを通知するための"PlayerDamagedEvent"というクラスを作成します。
  2. イベントリスナーの作成: イベントを受け取るオブジェクト(リスナー)がイベントを処理するためのメソッドを持つクラスを作成します。例えば、"PlayerDamageListener"というクラスを作成し、"OnPlayerDamaged"というメソッドを追加します。
  3. イベントの発行: イベントが発生した時に、パブリッシャーオブジェクトがイベントを作成し、それを登録されているすべてのリスナーオブジェクトに通知します。
  4. リスナーの登録と解除: リスナーオブジェクトは、イベントを受け取るためにパブリッシャーオブジェクトに登録します。また、不要になった場合には登録を解除することもできます。

このようにすることで、イベントの発生元と受け取り先を疎結合に保ちながら、異なるオブジェクト間での通信や通知を簡単に行うことができます。

サンプル

以下にUnityにおけるオブザーバーパターンのサンプルコードを示します。この例では、プレイヤーがダメージを受けたことを通知するシステムを実装します。

using UnityEngine;
using System;

// プレイヤーがダメージを受けたことを通知するイベントクラス
public class PlayerDamagedEvent : EventArgs
{
    public int damageAmount;

    public PlayerDamagedEvent(int damage)
    {
        damageAmount = damage;
    }
}

// プレイヤーのダメージを受け取るリスナークラス
public class PlayerDamageListener
{
    public void OnPlayerDamaged(object sender, PlayerDamagedEvent e)
    {
        Debug.Log("プレイヤーがダメージを受けました! ダメージ量: " + e.damageAmount);
    }
}

// プレイヤークラス
public class Player : MonoBehaviour
{
    // ダメージを受けたことを通知するイベント
    public event EventHandler<PlayerDamagedEvent> OnPlayerDamaged;

    private void Start()
    {
        PlayerDamageListener damageListener = new PlayerDamageListener();
        // リスナーをイベントに登録
        OnPlayerDamaged += damageListener.OnPlayerDamaged;
    }

    private void Update()
    {
        // プレイヤーがダメージを受けたと仮定し、イベントを発行
        if (Input.GetKeyDown(KeyCode.Space))
        {
            PlayerDamagedEvent damageEvent = new PlayerDamagedEvent(10);
            OnPlayerDamaged?.Invoke(this, damageEvent);
        }
    }
}

上記のコードでは、PlayerDamagedEventクラスがイベントのデータを保持し、PlayerDamageListenerクラスがイベントを受け取るためのメソッドを持ちます。Playerクラスでは、OnPlayerDamagedイベントを定義し、Update()メソッド内でイベントを発行しています。

Start()メソッドでは、PlayerDamageListenerオブジェクトを作成し、OnPlayerDamagedイベントに対してOnPlayerDamagedメソッドを登録しています。これにより、プレイヤーがダメージを受けた際にOnPlayerDamagedメソッドが呼び出されるようになります。

Update()メソッドでは、仮のダメージ受け取り操作として、スペースキーが押された場合にPlayerDamagedEventを作成し、OnPlayerDamagedイベントを発行しています。

OnPlayerDamaged?.Invoke(this, damageEvent);?.演算子は、イベントがnullでない場合にのみイベントを発行するための安全な呼び出しを行います。

このサンプルでは、プレイヤーのダメージを受けたことを通知するイベントシステムが実装されています。他のオブジェクトでこのイベントを受け取りたい場合は、同様にリスナーを作成してイベントに登録すれば、プレイヤーのダメージイベントを監視できます。