イベントアセット

abstract

名前空間:SilCilSystem.Variables (ジェネリック版はSilCilSystem.Variables.Generic)

継承:VariableAsset

Assembly:SilCilSystem


異なるスクリプト間でのメソッドの実行ができます。 メソッドの実行が可能なGameEventとメソッドの登録のみ可能なGameEventListenerがあります。

クラス一覧

引数なしのメソッドを扱う

抽象クラス 役割
GameEvent Publishでメソッドの実行
GameEventListener Subscribeでメソッドの登録

引数1つのメソッドを扱う

抽象クラス 役割 備考
GameEvent<T> Publishでメソッドの実行 GameEventを継承
GameEventListener<T> Subscribeでメソッドの登録 GameEventListenerを継承

Unity2019ではジェネリッククラスをシリアライズすることができないため、 よく使う型については非ジェネリックな抽象クラスを用意しています。 実際のスクリプトでは以下のクラスを使用することになると思います。

Primitive

型 クラス 登録専用クラス
bool GameEventBool GameEventBoolListener
string GameEventString GameEventStringListener
int GameEventInt GameEventIntListener
float GameEventFloat GameEventFloatListener

UnityEngineのstruct型

型 クラス 登録専用クラス
Vector2 GameEventVector2 GameEventVector2Listener
Vector2Int GameEventVector2Int GameEventVector2IntListener
Vector3 GameEventVector3 GameEventVector3Listener
Vector3Int GameEventVector3Int GameEventVector3IntListener
Color GameEventColor GameEventColorListener
Quaternion GameEventQuaternion GameEventQuaternionListener

使用例

例えば、キーを押すたびにサイコロを振るスクリプトを作ってみます。

using UnityEngine;
using SilCilSystem.Variables;

public class RollDice : MonoBehaviour
{
    // イベントアセットをシリアライズしてインスペクタで設定可能に.
    [SerializeField] private GameEventInt m_onDiceRolled = default;

    private void Update()
    {
        if (Input.anyKeyDown)
        {
            // キーを押すたびに1から6までの乱数値を生成.
            int value = Random.Range(1, 7);
            // メソッドを呼び出す.
            m_onDiceRolled.Publish(value);
        }
    }
}

サイコロの値をDebug.Logで表示するにはGameEventIntListenerを使用します。

using UnityEngine;
using SilCilSystem.Variables;

public class DebugDice : MonoBehaviour
{
    // イベントアセットをシリアライズしてインスペクタで設定可能に.
    [SerializeField] private GameEventIntListener m_onDiceRolled = default;

    private void Start()
    {
        // 実行するメソッドを登録する. 第2引数に指定したGameObjectが破棄されたらイベント解除される.
        m_onDiceRolled.Subscribe(x => Debug.Log(x), gameObject);
    }
}

インスペクタ上で同じイベントアセットを設定すれば、両者の連携が可能になります。 メニューからint型のイベントアセットを作成して設定します。

イベントアセットをインスペクタ上で設定する

変数の値が変化した場合に処理を呼ぶ

変数の値が変化した場合に処理を呼びたい場合には、 変数アセットのサブアセットになっているGameEventListenerが利用できます。 使用方法はこちらが参考になります。

使用上の注意点

引数が1つのSubscribeメソッドを使用する場合はIDisposableが返り値になります。 そのDisposeメソッドの呼び出しでイベント解除になるため、呼び出し忘れに気を付けてください。 OnDisableやOnDestroyメソッドなどを利用しましょう。

IDisposableに関する機能を用意しています。

実装

イベントアセットはイベントハンドラをメンバに持つ単純なScriptableObejctとして実装されています。 例えば、GameEventを継承したクラスEventNoArgsの具体的な実装は以下です。

// 使用する際は具体的な型(この場合はEventNoArgs)を知る必要がないのでinternalで実装.
internal class EventNoArgs : GameEvent
{
    private event Action m_event;
    public override void Publish() => m_event?.Invoke();
    public override IDisposable Subscribe(Action action)
    {
        // イベントを登録.
        m_event += action;
        // 解除用のIDisposableクラスを返す.
        return DelegateDispose.Create(() => m_event -= action);
    }
}

※登録解除用のIDisposableの生成に用いているDelegateDisposeについてはこちら。

読み取り専用クラスGameEventListenerの具体的な実装はGameEventを参照に持ち、値を返します。

internal class EventNoArgsListener : GameEventListener
{
    [SerializeField] private EventNoArgs m_event = default;
    public override IDisposable Subscribe(Action action) => m_event.Subscribe(action);
}

これら2つを機能させるためには、それぞれのアセットを作るだけでなく、参照関係も設定しなければなりません。 つまり、機能させるには以下の3つのステップが必要です。

  1. EventNoArgsアセットを作成する
  2. EventNoArgsListenerアセットを作成する
  3. EventNoArgsListenerアセットのm_eventに1で作成したEventNoArgsアセットを設定する

これを作成のたびにやるのは面倒なので、エディタ拡張で対応しています。 アセットをすべて表示するのは煩わしいので、サブアセットにしてHideFlagsを設定することで非表示にしています。 アセットのインスペクタにあるShow/Hideを押すことで表示/非表示を切り替えられます。 細かく参照設定を行いたい場合は表示するとよいでしょう。

サブアセットの表示を切り替える

※変更を反映するにはプロジェクトビューを更新させなければならないようです。この辺り、エディタ拡張でうまくやることができませんでした。


ドキュメントトップへ

ダウンロードページへ