从MonoBehaviour继承的脚本类有一个特定的生命周期,可以在Unity的文档里面看到:
一般情况下,一个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之前调用。但是Update和LateUpdate的相对顺序是对的。
测试结果3:

LateUpdate跑到了Update前面,悲剧了。
所以平时编码不能太过依赖Update系列方法的调用顺序,这些东西不可靠。
相比之下,Awake => OnEnable => Start和OnDisable => OnDestroy还是很可靠的。
资源加载中的脚本生命周期测试
如果脚本是资源的一部分,那么这个地方需要格外小心。
- 测试通过
AssetBundle加载 - 测试通过
Resources加载
实际测试发现,不管是那种方式加载资源,对于被加载的资源goA(GameObject)来说,如果goA在打AssetBundle时或者在Resources文件夹中active是false,那么Instantiate生成的对象上面的脚本不会执行任何生命周期函数。
如果goA的active是true,但是上面的脚本enable是false,那么Instantiate后,脚本只会触发Awake,销毁时触发OnDestroy。
OnEnable和OnDisable一定是成对调用。只要触发了Awake,则对象销毁时一定会触发OnDestroy。
任何生命周期函数都发生在Instantiate之后。刚从AssetBundle中取出的对象,如果没有Instantiate,那这个对象就是个“哑对象”,Instantiate之后这个对象就被激活了。
以上测试基于 Unity5.3.4f1
转载请注明出处:
This work is licensed under a MIT License.