Unityな日々(Unity Geek)

Unityで可視化アプリを開発するための試行錯誤の覚書

UnityEventのコールバック関数に、動的に引数を渡す

unitygeek.hatenablog.com

上のブログに書いたように、UnityEventをpublic変数で定義すると、インスペクタにUnityEvent変数が表示され、インスペクタ上でコールバック関数を追加・削除できる。

f:id:yasuda0404:20171219125311p:plain

コールバック関数が引数をとる場合は、インスペクタ上に引数を設定するフィールドも表示される。

f:id:yasuda0404:20171219125533p:plain

UnityEventの問題(制約)

しかし、この方法には次のような問題(制約)がある。

  1. 引数は1つしか取れない。引数が2つ以上あるメソッドは、インスペクタのリストに表示されず、指定することができない。

  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つに分けられている。

f:id:yasuda0404:20171219131927p:plain

'Static'は従来のとおり、インスペクタ上で「静的に」引数を指定するもの。

一方、'Dynamic'は、スクリプト内でInvoke()の引数を「動的に」指定するもの。

上の例では、同じ'ShowPage(int)'メソッドは、Dynamic/Staticの両方に表示されている。引数を動的に指定したい場合は、'Dynamic'の方を使う。

なお、UnityEventで渡せる引数は最大4つ(<T0, T1, T2, T3>)である。