Unity事件函数的执行顺序

Posted a_codecat

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Unity事件函数的执行顺序相关的知识,希望对你有一定的参考价值。

事件函数的执行顺序


脚本生命周期流程图



场景加载时

这些函数在场景开始时被调用(场景中的每个对象一次)
  • Awake:此函数总是在任何 Start 函数之前以及在预制件被实例化之后调用(如果 GameObject 在启动期间处于非活动状态,则在激活之前不会调用 Awake。)

  • OnEnable:(仅在对象处于活动状态时调用):此函数在对象启用后立即调用。 这在创建 MonoBehaviour 实例时发生,例如加载关卡或 GameObject的脚本组件被实例化时。


Editor

  • Reset:当脚本首次附加到对象时以及使用 Reset 命令时,都会调用 Reset 来初始化脚本的属性。

  • OnValidate:每当设置脚本的属性时调用 OnValidate,包括反序列化对象时,这可能在不同时间发生,例如在编辑器中打开场景时和域重新加载后。


Before the first frame update

  • Start:只有在启用脚本实例的情况下,才会在第一帧更新之前调用 Start。

Update Order

  • FixedUpdate:FixedUpdate 通常比 Update 更频繁地被调用。 如果帧率低,它可以每帧调用多次,如果帧率高,它可能根本不会在帧之间调用。 所有物理计算和更新都在 FixedUpdate 之后立即发生。 在 FixedUpdate 中应用移动计算时,您不需要将您的值乘以 Time.deltaTime。 这是因为 FixedUpdate 是在可靠的计时器上调用的,与帧速率无关。

  • Update:每帧调用一次。

  • LateUpdate:在Update后,每帧调用一次 LateUpdate。 在 LateUpdate 开始时,在 Update 中执行的任何计算都将完成。 LateUpdate 的一个常见用途是跟随第三人称相机。 如果您让您的角色在 Update 中移动和转动,您可以在 LateUpdate 中执行所有相机移动和旋转计算。 这将确保角色在相机跟踪其位置之前已经完全移动。


Animation update loop

  • OnStateMachineEnter:在状态机更新步骤中,当控制器的状态机进行一个流经 Entry 状态的转换时,在第一个更新帧上调用此回调。 不会调用它来转换到 StateMachine 子状态。

  • OnStateMachineExit:在状态机更新步骤中,当控制器的状态机进行流经退出状态的转换时,将在最后一个更新帧上调用此回调。 不会调用它来转换到 StateMachine 子状态。

  • Fire Animation Events:从上次更新时间和当前更新时间之间采样的所有剪辑调用所有动画事件。

  • StateMachineBehaviour (OnStateEnter/OnStateUpdate/OnStateExit):一个层最多可以有3个活动状态:当前状态、中断状态和下一状态。 使用定义 OnStateEnter、OnStateUpdate 或 OnStateExit 回调的 StateMachineBehaviour 组件为每个活动状态调用此函数。

  • OnAnimatorMove:每个更新帧,为每个 Animator 组件调用一次,修改Root Motion

  • StateMachineBehaviour(OnStateMove):在每个活动状态上使用定义此回调的 StateMachineBehaviour 调用。

  • OnAnimatorIK:设置动画 IK。 对于启用 IK 通道的每个 Animator Controller 层调用一次。

  • StateMachineBehaviour(OnStateIK):在启用 IK 通道的层上定义此回调的 StateMachineBehaviour 组件在每个活动状态上调用。

  • WriteProperties:将所有其他动画属性从主线程写入场景。


Rendering

  • OnPreCull:在相机剔除场景之前调用。剔除确定哪些对象对相机可见。 OnPreCull 在剔除发生之前被调用。

  • OnBecameVisible/OnBecameInvisible:当对象对任何相机可见/不可见时调用。

  • OnWillRenderObject:如果对象可见,则为每个摄像机调用一次。

  • OnPreRender:在相机开始渲染场景之前调用。

  • OnRenderObject:在所有常规场景渲染完成后调用。此时您可以使用 GL 类或 Graphics.DrawMeshNow 来绘制自定义几何图形。

  • OnPostRender:在相机完成渲染场景后调用。

  • OnRenderImage:场景渲染完成后调用,允许后期处理图像。

  • OnGUI:每帧调用多次以响应 GUI 事件。首先处理 Layout 和 Repaint 事件,然后是每个输入事件的 Layout 和键盘/鼠标事件。

  • OnDrawGizmos 用于绘制 Gizmos在场景视图中出于可视化目的。

注意:这些回调仅适用于内置渲染管线。


Coroutines

正常的协程更新在 Update 函数返回后运行。 协程是一个可以暂停执行(yield)直到给定的 YieldInstruction 完成的函数。
  • yield 在下一帧调用所有 Update 函数后协程将继续。
  • yield WaitForSeconds 在为帧调用所有更新函数后,在指定的时间延迟后继续。
  • yield WaitForFixedUpdate 在所有脚本上调用所有 FixedUpdate 后继续。 如果协程在 FixedUpdate 之前产生,则它在当前帧的 FixedUpdate 之后恢复。
  • yield WWW 在 WWW 下载完成后继续。
  • yield StartCoroutine 链接协程,并等待 MyFunc 协程首先完成。

When the Object is destroyed

  • OnDestroy:此函数在对象存在的最后一帧的所有帧更新之后调用(对象可能会响应 Object.Destroy 或在场景关闭时被销毁)。

When quitting

这些函数会在场景中的所有活动对象上调用:

OnApplicationQuit:此函数在应用程序退出之前在所有游戏对象上调用。 在编辑器中,当用户停止播放模式时调用它。

OnDisable:当行为被禁用或不活动时调用此函数。

Unity3D中自带事件函数的执行顺序

在Unity3D脚本中,有几个Unity3D自带的事件函数按照预定的顺序执行作为脚本执行。其执行顺序如下:

编辑器(Editor)

  • Reset:Reset函数被调用来初始化脚本属性当脚本第一次被附到对象上,并且在Reset命令被使用时也会调用。
    编者注:Reset是在用户点击Inspector面板上Reset按钮或者首次添加该组件时被调用。Reset最常用于在见识面板中给定一个默认值。

第一次场景加载(First Scene Load)
这些函数会在一个场景开始(场景中每个物体只调用一次)时被调用。

  • Awake:这个函数总是在任何Start()函数之前一个预设被实例化之后被调用,如果一个GameObject是非激活的(inactive),在启动期间Awake函数是不会被调用的直到它是活动的(active)。
  • OnEnable:只有在对象是激活(active)状态下才会被调用,这个函数只有在object被启用(enable)后才会调用。这会发生在一个MonoBehaviour实例被创建,例如当一个关卡被加载或者一个带有脚本组件的GameObject被实例化。

注意:当一个场景被添加到场景中,所有脚本上的Awake()和OnEable()函数将会被调用在Start()、Update()等它们中任何函数被调用之前。自然的,当一个物体在游戏过程中被实例化时这不能被强制执行。

第一帧更新之前(Before the first frame update)

  • Start:只要脚本实例被启用了Start()函数将会在Update()函数第一帧之前被调用。

对于那些被添加到场景中的物体,所有脚本上的Start()函数将会在它们中任何的Update()函数之前被调用,自然的,当一个物体在游戏过程中被实例化时这不能被强制执行。

在帧之间(In between frames)

  • OnApplicationPause:这个函数将会被调用在暂停被检测有效的在正常的帧更新之间的一帧的结束时。在OnApplicationPause被调用后将会有额外的一帧用来允许游戏显示显示图像表示在暂停状态下。

更新顺序(Update Order)

当你在跟踪游戏逻辑和状态,动画,相机位置等的时候,有几个不同的事件函数你可以使用。常见的模式是在Update()函数中执行大多数任务,但是也有其它的函数你可以使用。

  • FixedUpdate:FixedUpdate函数经常会比Update函数更频繁的被调用。它一帧会被调用多次,如果帧率低它可能不会在帧之间被调用,就算帧率是高的。所有的图形计算和更新在FixedUpdate之后会立即执行。当在FixedUpdate里执行移动计算,你并不需要Time.deltaTime乘以你的值,这是因为FixedUpdate是按真实时间,独立于帧率被调用的。
  • Update:Update每一帧都会被调用,对于帧更新它是主要的负荷函数。
  • LateUpdate:LateUpdate会在Update结束之后每一帧被调用,任何计算在Update里执行结束当LateUpdate开始时。LateUpdate常用为第三人称视角相机跟随。

渲染(Rendering)

  • OnPreCull:在相机剔除场景前被调用。剔除是取决于哪些物体对于摄像机是可见的,OnPreCull仅在剔除起作用之前被调用。
  • OnBecameVisible/OnBecameInvisible:当一个物体对任意摄像机变得可见/不可见时被调用。
  • OnPreRender:在摄像机开始渲染场景之前调用。
  • OnRenderObject:在指定场景渲染完成之后调用,你可以使用GL类或者Graphics.DrawMeshNow 来绘制自定义几何体在这里。
  • OnPostRender:在摄像机完成场景渲染之后调用。
  • OnRenderImage(Pro Only):在场景徐然完成之后允许屏幕图像后期处理调用。
  • OnGUI:为了响应GUI事件,每帧会被调用多次(一般最低两次)。布局Layout和Repaint事件会首先处理,接下来处理的是是通过
    Layout和键盘/鼠标事件对应的每个输入事件。
  • OnDrawGizmos:用于可视化的绘制一些小玩意在场景视图中。

协同程序(Coroutines)

正常的协同程序更新是在Update函数返回之后运行。一个协同程序是可以暂停执行(yield)直到给出的依从指令(YieldInstruction )完成,写成的不同运用:

  • yield:在所有的Update函数都已经被调用的下一帧该协程将持续执行。
  • yield WaitForSeconds:一段指定的时间延迟之后继续执行,在所有的Update函数完成调用的那一帧之后。
  • yield WaitForFixedUpdate:所有脚本上的FixedUpdate函数已经执行调用之后持续。
  • yield WWW:在WWW下载完成之后持续。
  • yield StartCoroutine:协同程序链,将会等到MuFunc函数协程执行完成首先。

销毁(When the Object is Destroyed)

  • OnDestory:这个函数在会在一个对象销毁前一帧调用,会在所有帧更新一个对象存在的最后一帧之后执行,对象也许会响应Object.Destroy 或一个场景关闭时被销毁。

退出游戏(When Quitting)
这些函数会在你场景中所有的激活的物体上调用:

    • OnApplicationQuit:这个函数在应用退出之前的所有游戏物体上调用,在编辑器(Editor)模式中会在用户停止PlayMode时调用,在网页播放器(web player)中会在网页视图关闭时调用。
    • OnDisable:当行为变为非启用(disable)或非激活(inactive)时调用

以上是关于Unity事件函数的执行顺序的主要内容,如果未能解决你的问题,请参考以下文章

Unity3D中自带事件函数的执行顺序

Unity事件函数的执行顺序

Unity3D日常开发Unity3D中实现不同脚本之间的执行顺序控制

Unity---脚本事件函数和生命周期

Unity3D中脚本的执行顺序和编译顺序(vs工程引用关系)

Unity脚本的生命周期