Script Execution Order Settings

Unity MonoBehaviour不同脚本中的Awake、OnEnable和Update方法的回调顺序默认情况下是由脚本的加载顺序决定的,而脚本的加载顺序是不确定的,因此一个脚本的Awake是否先于另一个脚本的Awake被调用也就无法确定。

Unity提供了一个Script Execution Order Settings来供开发者解决这个问题,调整不同脚本的回调顺序(限于Awake、OnEnable和Update)。 它的实现方式如下。

class MonoBehaviour通过m_Methods保存了一个MonoBehaviour中部分可回调方法的数组,这些方法通过一个枚举值索引。

这个枚举中看不到OnEnable、OnDisable等方法,这是因为该枚举用于引擎内部,暴露给C#层的方法名算是它的别名,可以用下图一一对应。

Awake的回调顺序控制主要是在AwakeFromLoadQueue里通过控制加载顺序来实现。编辑器下会即时调用SortBehaviourItemByExecutionOrderAndInstanceID来实时排序,而游戏中是Build过程将排序写入了场景文件。

Update由专门的BaseBehaviourManager来管理,BaseBehaviourManager中有一个m_Lists,正是它通过Script Execution Order将同一order的脚本Update串连起来、将不同order的脚本Update按顺序调用。

Unity中有4个BaseBehaviourManager,分别是BehaviourManager、FixedBehaviourManager、LateBehaviourManager和UpdateManager。前3个分别负责调用MonoBehaviour的Update、FixedUpdate和LateUpdate方法,而最后一个UpdateManager实际和BehaviourManager作用一样也是调用Update,但并没有看到有脚本的方法注册到它里面。

从PlayerLoop里的调用顺序来看依次是:GetFixedBehaviourManager ().Update (); GetBehaviourManager ().Update (); GetLateBehaviourManager ().Update (); GetUpdateManager ().Update ();