Unity MonoBehaviour 边界条件下的生命周期

Posted by QXSoftware on March 23, 2017

MonoBehaviour继承的脚本类有一个特定的生命周期,可以在Unity的文档里面看到:

monobehaviour_flowchart

一般情况下,一个MonoBehaviour的生命周期如下:

Awake => OnEnable => Start => FixedUpdate => Update => LateUpdate => OnDisable => OnDestroy

其中,FixedUpdate一帧内可能会执行多次。不过实际测试的结果并不是严格遵循这个结论的。

简单脚本生命周期测试

测试分为以下三种情况:

  • 直接在场景中摆好一个GameObject,并且在上面挂上DynamicAdd1脚本
  • 动态创建GameObject,然后动态添加DynamicAdd1脚本
  • 动态创建GameObject go,然后go.SetActive(false),然后添加脚本DynamicAdd1 dyn,然后dyn.enabled = false,然后等一秒go.SetActive(true),再等一秒dyn.enabled = true

测试结果1:

这个是符合预期的,也是和Unity文档描述相符的。

测试结果2:

这个测试中,FixedUpdate没有在Update之前调用。但是UpdateLateUpdate的相对顺序是对的。

测试结果3:

LateUpdate跑到了Update前面,悲剧了。

所以平时编码不能太过依赖Update系列方法的调用顺序,这些东西不可靠。

相比之下,Awake => OnEnable => StartOnDisable => OnDestroy还是很可靠的。

资源加载中的脚本生命周期测试

如果脚本是资源的一部分,那么这个地方需要格外小心。

  • 测试通过AssetBundle加载
  • 测试通过Resources加载

实际测试发现,不管是那种方式加载资源,对于被加载的资源goA(GameObject)来说,如果goA在打AssetBundle时或者在Resources文件夹中activefalse,那么Instantiate生成的对象上面的脚本不会执行任何生命周期函数。

如果goAactivetrue,但是上面的脚本enablefalse,那么Instantiate后,脚本只会触发Awake,销毁时触发OnDestroy

OnEnableOnDisable一定是成对调用。只要触发了Awake,则对象销毁时一定会触发OnDestroy

任何生命周期函数都发生在Instantiate之后。刚从AssetBundle中取出的对象,如果没有Instantiate,那这个对象就是个“哑对象”,Instantiate之后这个对象就被激活了。

以上测试基于 Unity5.3.4f1


转载请注明出处:

This work is licensed under a MIT License.