从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.