Unity脚本周期概览
运行Unity的脚本时,程序将会按照预定的顺序去执行相应的函数,从脚本的初始化到脚本的销毁,构成了脚本的生命周期。Unity脚本的生命周期预览图如下:
生命周期的不同阶段
上图中的多个函数可以根据其执行的时间段分为以下不同阶段。
首场景加载阶段
以下的函数在场景加载时调用,且在加载时只调用一次(OnEnable可能在后续进行多次调用)
- Awake:在Prefab进行实例化后调用,位于Start函数前。(若GameObject在一开始就处于非激活状态时,Awake则不会调用,直到该GameObject被激活)
- OnEnable:该函数在GameObject被激活时被调用。GameObject激活则是发生在一个MonoBehaviour实例被创建的时候。例如场景被加载或者一个拥有该脚本组件的GameObject被实例化时。注意: OnEnable首次调用是紧接Awake之后,对于同一脚本,若有多个物体创建时,是先执行完A物体的Awake->OnEnable函数,然后再执行B物体的Awake->OnEnable函数
- OnLevelWasLoaded:这个函数是用于通知有场景已经加载结束
编辑器阶段
- Reset:当脚本被添加为物体的组件时,Reset会被调用用于初始化脚本的属性。或者当开发者执行Reset的编辑器操作时也会被调用。
第一帧更新前的阶段
- Start:当脚本实例是可用状态时,Start会在第一帧更新前调用
注:Start会在当前场景的所有物体执行Update前执行。
帧与帧之间的阶段
- OnApplicationPause:该函数会在当前帧结束后下一帧开始前且检测到暂停的时候回调
更新顺序
当我们跟踪游戏的逻辑进行,如相机位置、人物动作的变化时我们会用到以下的更新函数,我们可以根据情况使用Update之外的函数来达到我们的目的
- FixedUpdate:FixedUpdate一般会比Update调用得更频繁,当帧率较低时,他一帧内可能会调多次。所有的物理计算和Update函数都是在FixedUpdate函数之后。(是一个独立于帧率外的回调函数)
- Update:一帧只会被调用一次。
- LateUpdate:一帧只会被调用一次,位于Update函数之后。该函数一般用于Update结束后的后续处理,例如 Update函数中来进行人物的移动,而LateUpdate则用于改变第三人称相机的位置,这将能保证相机更新逻辑的准确。
渲染阶段
- OnPreCull:相机剔除场景前被调用,属于渲染流水线的一个环节。
- OnBecameVisible/OnBecameInvisible:当物体在任何相机中可见/不可见时调用。注意:Scene视图的相机也需要考虑进去
- OnWillRenderObject:当物体在相机中可见时,他将为各个相机调用一次
- OnPreRender:在相机开始渲染场景时调用
- OnRenderObject:在所有固定场景渲染完之后调用
- OnPostRender:在相机渲染完场景后调用
- OnRenderImage:场景渲染完使用,一般用于后期处理(如Glow)
- OnGUI:一帧会调用多次来响应GUI事件
- OnDrawGizmos :渲染Gizmos时调用
协程
普通的协程是在Update函数后进行更新的。
- yield:下一帧所有Update函数调用后,协程将会继续执行
- yield WaitForSeconds:等待固定的秒数后协程继续执行
- yield WaitForFixedUpdate:所有的FixedUpdate执行完后,协程继续执行
- yield WWW:WWW下载完成后,协程继续执行
- yield StartCoroutine XXFunc:链接协程,将会等XXFunc执行完后再继续
对象销毁阶段
- OnDestroy:在对象存在的最后一帧调用,在所有的更新方法结束后调用
注意:调用Destroy(GO)时会先调用OnDisable,然后在所有的更新方法结束后调用OnDestroy
应用退出阶段
在应用退出场景中的激活的对象会调用以下的函数:
- OnApplicationQuit:应用退出时所有的游戏物体将会调用此函数(Editor中进行Stop操作也会)
- OnDisable:当物体被设置为非激活状态时调用