为什么Unity使用反射来获取更新方法?


12

为什么为了不统一使用反射来访问MonoBehaviour像信息的方法AwakeUpdateStart,...?

使用反射会不会很慢?为什么不利用其他方法Template Method呢?它可以在MonoBehaviour基类中简单地将方法定义为抽象,并强制子类实现该方法。

Answers:


20

不是

如何调用更新

不,Unity每次需要调用一个方法时都不会使用System.Reflection查找魔术方法。

相反,第一次访问给定类型的MonoBehaviour时,将通过脚本运行时(Mono或IL2CPP)检查基础脚本是否定义了任何魔术方法,并缓存此信息。如果MonoBehaviour具有特定的方法,则会将其添加到适当的列表中,例如,如果脚本定义了Update方法,则会将其添加到需要每帧更新的脚本列表中。

在游戏过程中,Unity只需遍历这些列表并从中执行方法-就这么简单。同样,这就是为什么Update方法是公共的还是私有的都没关系的原因。

由于这样做的原因,我将主要向您(读者)介绍DMGregory的答案,该答案归结为两个相互矛盾的方面的平衡:

  1. 性能优化
  2. 轻松利用新开发人员

一个新的开发人员只希望它能够正常工作,而不必弄清楚“如何将它连接到事件系统?” 但它仍应以最小的开销快速运行。

在这两个约束内解决方案可能是最好的。或者至少是当时Unity开发团队能够提供的最好的工具。我们可能永远不会知道。


2
tl; dr相同的过程,不同的,更快的API。但是为什么他们不按照OP的要求选择其他方法呢?
温德拉

10
我们不应该否认旧的“不良设计”原因的可能性。在发布C#源代码之后,用户发现了大量的错误和无法解释的设计决策。一些游戏开发者终于能够理解他们多年来一直在与之抗争的那些意外行为。
Exerion '18 -10-29

除了技术性,这是新手首先要学习的内容,因此必须易于添加或跳过。
Nikaas

6
这种设计可能还有历史原因。Unity从他们自己的脚本语言开始,然后逐渐被C#淘汰。他们很自然地希望继续使用相同的模式,即使这意味着有点作弊。
菲利普

3
我认为我们可以有用地回答“ Unity通过这种方式可以实现什么”。与必须全部实现的抽象公共方法的集合相比,优点是什么?我们无法回答“ Unity开发人员在想什么?” 但是我们可以解决“为什么这种方法对引擎用户有用?”
DMGregory

10

它可以简单地将方法定义为MonoBehaviour基类中的抽象方法,并强制子类实现该方法。

Unity使用的系统的优点之一是您不必实现每个MonoBehaviour消息,消息有60多个

通常,我们只需要这些方法中的一种或几种即可。由于某些特定于2D / 3D物理,某些特定于相机或粒子系统,因此几乎没有任何一个脚本会需要所有这些脚本。

通过将不需要的消息保留为未实现,我们可以清楚地向运行时发出信号:“甚至不必费心在该对象上调用OnCollisionStay2D-我不需要它”

这可以是巨大的效率优势。现在,引擎可以筛选出一个短列表,以仅对场景中每帧需要自定义更新逻辑的〜20个对象调用Update,而不是构成所有场景或仅对物理事件做出响应的所有〜200个对象。


只是一个问题……据我所知(不是我个人),如果您有成千上万个GameObject,而所有这些都使用带有Update方法的脚本,则会对性能产生重大影响。另一种方法是使用列表并使用管理器脚本中的一个 Update方法仅遍历列表,这似乎要好得多。还是这样,还是已经改变了?-如果什么都没有改变,则意味着Unity的执行方式在性能方面远未达到最佳状态。
战斗

4
@Battle描述的内容与Draco18s引用自2015年的链接一致,我怀疑它仍然是正确的。能够在成千上万个对象上保留未定义的Update方法正是使此优化有效的原因。如果每个MonoBehaviour都有一个通过抽象基类定义的Update方法,如我在引用的问题部分所述,那么我们将无法将更新调用限制为仅经理列表的迭代。请注意,此问题解答并未解决“ Unity的方法是否最佳?” 但只有当前的方法可以受益。
DMGregory

我明白了,这确实是有道理的。感谢你的回答!
战斗

@Battle它仍然是正确的。尽管Unity的功能比其他功能要好,但与常规函数调用相比,其开销仍然更大。
Draco18s不再信任SE

@ Draco18s-是的 很早以前,我已经为我的项目实现了一个UpdateManager,它负责该优化。我只是想确认一下它仍然需要/有用。
战斗
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.