キノコの自省録

日々適当クリエイト

Unity FungusのInvokeMethodとCallMethodは何が違うのか

Fungusを使ったメソッド呼び出しには、InvokeMethodとCallMethodの2種類があります。何が違うのでしょうか?

CallMethodはGameObject.SendMessage()

ヘルプにも書いてありますが、CallMethodは、実際にはGameObject.SendMessage()を呼び出しています。 即ち、Hogeと言うメソッドを呼び出すように設定した場合、 targetObject.SendMessage("Hoge", xxx); が実行されると言うことです。

InvokeMethodはリフレクションを使う

こちらもヘルプに書いてありますが、InvokeMethodは、Fungus内部で直接C#のReflection機能を使用して、メソッドを呼び出します。 Reflectionを実行するメソッドがInvoke()なため、InvokeMethodという名前がついているものと思います。

Recflectionとは?

Reflection(リフレクション)とは、「文字列から、同名のメソッドを見つけて呼び出せるようにする」というハッキングまがいの手法です。 Androidの非公開メソッドを無理やりコールする時なんかにも使います。

コード上でもGameObject.Find();とか直接メソッド名書いてるじゃん!と思うかもしれませんが、これはビルド時には呼び出しアドレスに変換してしまっていますので、実行時には文字列とは言い難いモノになっています。

そうではなく、例えば、

  • 実行時に外部から読み込んだテキストファイル
  • ネットワーク越しに受け取った文字列
  • なんか入力された文字列

などを実行時に解析して、その解析文字列だけで実行できるようにする手法がリフレクションです。

f:id:kinokorori:20190823214904p:plain:w400
リフレクション(反射)

で、何が違うの?

簡単に言うと、CallMethodはUnityの用意したメソッド呼び出し方法を使い、InvokeMethodはFungus自体が用意したメソッド呼び出しを使います。 そして、CallMethodの先にあるSendMessageの実装がどうなっているのか不明なものの、実際にはReflectionを使用しているようです。要するに結局どちらもReflectionということです。

じゃあ大体同じじゃないの?と言われると、ええ、まあ、たぶん……という感じです。ただ、InvokeMethodの方が、

  • 呼び出し引数を細かく設定出来る
  • 戻り値をFungus引数で受け取れる

というメリットがあります。また、SendMessageの内部がブラックボックス過ぎて気にくわないという人にも安心です。個人的にはInvokeMethod使っておけばいいんじゃないの?というところ。

ちなみに、SendMessageの注意として、「Activeでないオブジェクトからは呼び出せない」という制約がありますが、これはInvokeMethodでも同じです。