コンポーネントで他のスクリプトのメソッドを呼び出すために登録させるエディタパーツです。
目次
UnityEventを使う
他のGameObjectのメソッドを呼び出したくて、それらのメソッドを登録するスクリプトを作りたいときにはUnityEventを使うと便利です。
具体的にはuGUIのButtonで使われているもので、一番よく見る事例だと思います。
この「On Click」のところですね。
こういったイベントを登録させたいときに使います。
指定の仕方は簡単で、
[SerializeField] private UnityEvent event1;
とすればもう、Inspectorに以下のように項目が出てきます。
イベントを登録する
あとはこいつに、呼び出すためのメソッドを指定していってやればOK。
右下の「+」をクリックすると、登録する項目が出てきます。
あとは「None」にGameObjectを入れてやると「No Function」のところにメソッドが出てくるので、呼び出したいものを選択します。
public void OnEvent1() { Debug.Log ("call event1"); }
このようなメソッドを作ったコンポーネントを登録してあるGameObjectを「None」に設定して、一覧から選択してみます。
このevent1をStartで呼んでみます。設定されたイベントを実行するには、Invokeを使用します。
void Start () { event1.Invoke (); }
で実行すると、コンソールに「call event1」が表示されました。
引数付きのイベントを登録する
引数を渡したいときも、メソッドにそのまま定義してしまえば良いです。
public void OnEventInt1(int val1) { Debug.Log ("call event int: " + val1); }
のようなメソッドを定義して選択すると、次のように出てきます。
この数字が、Invokeしたときにメソッドに渡される引数の値になります。
引数には他にも、stringや
GameObjectなどでも大丈夫です。
Inspectorから指定できるものであればいけそうなので、これだけでも応用が出来そうです。
ただ、この方法で渡せる引数は1つまでのようで、2つ以上の引数を持ったメソッドはリストに出てきません。
イベントに複数の引数を渡す
複数の引数を渡すためには、UnityEventを継承したクラスを作らなければいけないようです。なんか複雑になってきましたね…
UnityEventには、ジェネリックで型を指定するために定義されているクラスがあり、それを引数の型を指定して継承することで、引数付きUnityEventクラスを作成することになります。
int型を引数に取った以下のクラスを作り、
[Serializable] private class EventInt : UnityEvent<int> { }
これをSerializeFieldとしてInspectorで表示してみると以下のようになります。
タイトルのところに「Event Int (Int32)」と引数がありますね。
ジェネリックの定義は4つまであるので、引数4つまでいけるみたいです。なので最大を設定してみました。
タイトルが「Event Int 4 (Int32, Int32, Int32, Int32)」と、引数が4つになりました。
しかし、ここにInspectorから設定できるメソッドは、相変わらず引数無しまたは1つのもののみ。
また実行したときに、各イベントのInvokeメソッドは
eventInt.Invoke (100); eventInt4.Invoke (100, 200, 300, 400);
と指定した引数を取るのですが、実際に実行された場合はInspectorで設定した値がメソッドに渡されます。
Invoke実行時に引数を渡す
今まで登録してきたものは、「Static Parameters」にあるもので、Inspectorで値を固定しているものでした。
引数が2つ、3つ、4つのメソッドを登録する、またはInvokeで指定した値を引数として渡すためには、Dyamicにあるメソッドを指定して登録します。
例えば、引数を4つ持った、次のメソッドを登録したいとします。
public void OnEventInt4(int val1, int val2, int val3, int val4) { Debug.Log ("call event int4: " + val1+" : "+val2+" : "+val3+" : "+val4); }
これを先ほどのEventInt4のInspectorから指定するためには、「Dynamic」のところにあるメソッドを指定します。
これを指定すると以下のように、引数を設定する項目が出てこなくなります。
その代わり、Invoke時に
eventInt4.Invoke (100, 200, 300, 400);
と指定すると、その指定した値が渡り、
call event int4: 100 : 200 : 300 : 400
と出てきます。
引数に指定できる型について
あとは引数の型。UnityEventを継承したときにジェネリックで指定できる型は、クラスであれば自作クラスでも大丈夫みたいです。
public class EventArgClass { }
とか適当に作って、
[Serializable] private class EventArgSample : UnityEvent<EventArgClass> { }
としてやっても、
ちゃんと指定できる。
しかしstructは駄目でした。イベントクラスは作れるのですが、設定できるファンクションとして出てこなかった。
また引数が1つでも、InspectorのStaticには出てきませんでした。ここに出すには、引数として使用するクラスがMonoBehaviourを継承していればよさそうです。
以下のクラスを作ってジェネリックに指定した場合、
public class EventArgClass2 : MonoBehaviour { // Use this for initialization void Start () { } // Update is called once per frame void Update () { } }
引数にコンポーネントも指定できました。
Static Parametersは型が関係なく呼び出される
ここでですね、int型の引数で作ったイベントに、int型とstring型のメソッドを登録してみました。
これを実行した結果はこうでした。
call event int: 1 call event string: int event
上が引数int型のもの、下が引数string型のものです。
この結果から、Static ParametersはInspectorで指定されたものをそのまま実行しているだけで、UnityEventで指定した型のチェックをしていないことが分かります。
ここがゆるいのは便利なときもあり、厄介なバグになることもありそうです。この挙動は覚えておくと良いかもしてません…
参考: