上のブログに書いたように、UnityEventをpublic変数で定義すると、インスペクタにUnityEvent変数が表示され、インスペクタ上でコールバック関数を追加・削除できる。
コールバック関数が引数をとる場合は、インスペクタ上に引数を設定するフィールドも表示される。
UnityEventの問題(制約)
しかし、この方法には次のような問題(制約)がある。
引数は1つしか取れない。引数が2つ以上あるメソッドは、インスペクタのリストに表示されず、指定することができない。
引数はインスペクタ上で静的に指定され、実行時にスクリプトで動的に指定することができない。
コールバック関数の引数を動的に指定する
UnityEventのリファレンスを見ると、UnityEvent以外に、UnityEvent<T0>
, UnityEvent<T0, T1>
, UnityEvent<T0, T1, T2>
, UnityEvent<T0, T1, T2, T3>
の4つのGenericsがある。これを使えば、UnityEventで引数を渡せそうだ。
しかし、
public UnityEvent<string> TestEvent;
のように書いてもインスペクタには何も表示されない。
実はUnityEventクラスのGenericsは抽象クラスのため、継承クラスでしか使えない。
UnityEventで引数を渡すには(Genericsを使うには)、UnityEventのGenerics形を継承した独自クラスを定義する。
独自クラスは[Serializable]でシリアル化する(でないとインスペクタに表示されない)。
[Serializable] public class MyEvent : UnityEvent<string> { } [SerializeField] MyEvent OnChange; ... ... OnChange.Invoke("MyEvent"); //引数付きイベントの発行
インスペクタでのコールバック関数の設定
コールバック関数の引数を動的に指定するには、もうひとつ注意点がある。
上のように定義した独自イベントに、インスペクタ上でコールバック関数を指定する際、設定可能な関数一覧リストは、'Dynamic'と'Static'の2つに分けられている。
'Static'は従来のとおり、インスペクタ上で「静的に」引数を指定するもの。
一方、'Dynamic'は、スクリプト内でInvoke()の引数を「動的に」指定するもの。
上の例では、同じ'ShowPage(int)'メソッドは、Dynamic/Staticの両方に表示されている。引数を動的に指定したい場合は、'Dynamic'の方を使う。
なお、UnityEventで渡せる引数は最大4つ(<T0, T1, T2, T3>)である。