Unityがリフレクションを使用して更新メソッドを取得するのはなぜですか?


12

なぜアクセスするために、ユニティ使用リフレクションを行うMonoBehaviourようなメッセージ法AwakeUpdateStart、...?

リフレクションを使用するのは遅いのではないでしょうか?なぜ他のアプローチを利用しないのTemplate Methodですか?MonoBehaviour基本クラスでメソッドを抽象として定義し、サブクラスにそれを実装させるだけです。

回答:


20

それはしません

Updateの呼び出し方法

いいえ、Unityは、メソッドを呼び出す必要があるたびに、魔法のメソッドを見つけるためにSystem.Reflectionを使用しません。

代わりに、特定のタイプのMonoBehaviourに初めてアクセスしたときに、基礎となるスクリプトがスクリプトランタイム(MonoまたはIL2CPPのいずれか)で検査され、マジックメソッドが定義されていて、この情報がキャッシュされているかどうかが確認されます。MonoBehaviourに特定のメソッドがある場合は、適切なリストに追加されます。たとえば、スクリプトにUpdateメソッドが定義されている場合は、フレームごとに更新する必要があるスクリプトのリストに追加されます。

ゲーム中、Unityはこれらのリストを反復処理し、そこからメソッドを実行するだけです—とても簡単です。また、Updateメソッドがパブリックかプライベートかが問題にならないのはこのためです。

この方法で行われる理由については、主に読者(読者)にDMGregoryの回答を参照します。これは、2つの競合する事柄のバランスに要約されます。

  1. パフォーマンスの最適化
  2. 新規開発者の使いやすさ

新しい開発者は、それを機能させたいだけで、「これをイベントシステムに接続するにはどうすればよいですか」を理解する必要はありません。ただし、オーバーヘッドは最小限で、高速に実行されます。

ソリューションはおそらく、これらの2つの制約の範囲内で達成できる最良のものです。または、少なくとも、当時Unity開発チームが思いついた最高のものです。知らないかもしれません。


2
tl; dr同じプロセス、異なる、より高速なAP​​I。しかし、なぜOPから求められた別の方法を選択しなかったのですか?
wondra

10
私たちは、昔ながらの「悪いデザイン」の理由の可能性を否定すべきではありません。cの放出後#ソースコードのユーザーが発見したトンミスや原因不明の設計上の決定のを。一部のゲーム開発者は、長年にわたって戦っていた予期しない動作をようやく理解することができました。
エクセルジョン2018年

これはさておき、専門知識は初心者が最初に学ぶことの1つなので、簡単に追加またはスキップできます。
Nikaas 2018年

6
このデザインには歴史的な理由もあるかもしれません。Unityは独自のスクリプト言語で始まりましたが、徐々にC#に移行しました。たとえそれが少しだまされるつもりであったとしても、彼らが同じパターンを使い続けたいと思ったのは当然です。
フィリップ

3
私たちは「Unityがこれによって何を達成するのか」など、便利に答えられると思います。すべて実装する必要がある抽象パブリックメソッドのコレクションに対する利点は何ですか。「Unity開発者は何を考えていたのですか?」には答えられません。しかし、「このアプローチがエンジンのユーザーに役立つ理由」に取り組むことができます。
DMGregory

10

MonoBehaviour基本クラスで抽象としてメソッドを定義し、サブクラスにそれを実装させるだけです。

Unityが使用するシステムの利点の1つは、60を超えるすべてのMonoBehaviourメッセージを実装する必要がないことです。

通常、必要なのは、これらのメソッドの1つまたはごく一部です。一部は2D / 3D物理に固有であり、一部はカメラまたはパーティクルシステムに固有であるため、1つのスクリプトですべてが必要になることはほとんどありません。

不要なメッセージを未実装のままにしておくことで、「このオブジェクトでOnCollisionStay2Dを呼び出さなくても、必要ない」ということをランタイムに明確に伝えることができます。

これにより、効率が大幅に向上します。これで、エンジンはショートリストをフィルターに掛けて、フレーム内のカスタム更新ロジックが必要なシーン内の〜20オブジェクトのみでUpdateを呼び出すことができます。


ただ質問です...私が知る限り(個人的にではありません)、何千ものGameObjectがあり、そのすべてがUpdateメソッドでスクリプトを使用する場合、パフォーマンスに大きな影響があります。代わりの方法は、リストを使用して、マネージャースクリプトのUpdateメソッドを1つだけ使用してリストを反復処理することです。これにより、パフォーマンスが大幅に向上します。それはまだ事実ですか、それともすでに変わりましたか?-何も変更がなければ、Unityの方法がパフォーマンスに関して最適に近いとは言えないことを意味します。
バトル

4
@Battleは、Draco18sが2015年から引用しているリンクと一致しており、それはまだ正しいと思います。これらの何千ものオブジェクトに対してUpdateメソッドを未定義のままにできることは、まさにこの最適化を機能させるものです。すべてのMonoBehaviourに、私が引用した質問のセクションで説明されているように、抽象基本クラスを介して定義されたUpdateメソッドがある場合、更新呼び出しをマネージャーのリスト反復のみに制限することはできません。このQ&Aでは、「Unityのアプローチは最適ですか?」ただし、現在のアプローチがどのように役立つかのみです。
DMGregory

ああ、なるほど、それは確かに理にかなっています。答えてくれてありがとう!
バトル

@Battleそれでも本当です。Unityは他の方法よりもパフォーマンスが優れていますが、通常の関数呼び出しよりもオーバーヘッドが多くなります。
Draco18sは、

@ Draco18s-はい。私はすでにプロジェクトにUpdateManagerを実装しており、その最適化をずっと前から処理しています。私はそれがまだ必要/有​​用であることの確認を求めていました。
バトル
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.