Version: 6000.3
语言: 中文
脚本执行顺序
自定义播放器循环

事件函数执行顺序

下图简要概述了在 MonoBehaviour 脚本组件生命周期内运行的事件函数的执行顺序。为了便于阅读,图表的范围仅限于脚本生命周期的关键部分,并为上下文提供了一些额外的内部子系统更新。完整的播放器循环是针对特定系统和子系统的更长、更复杂的更新序列,它们以定义的默认顺序一个接一个地运行。要检索完整的播放器循环及其所有系统,您可以使用 PlayerLoop API。您还可以使用此 API 通过删除系统、添加自己的系统和更改更新顺序来自定义播放器循环序列。

如需详细了解每个回调的含义和限制,请参阅 MonoBehaviour API 参考的消息部分。

MonoBehaviour 脚本生命周期内事件函数的执行顺序。
MonoBehaviour 脚本生命周期内事件函数的执行顺序。

场景加载和卸载前

上图中未显示的是SceneManager.sceneLoadedSceneManager.sceneUnloaded事件,允许您在场景场景包含游戏的环境和菜单。将每个唯一的场景文件视为一个独特的关卡。在每个场景中,你放置你的环境、障碍物和装饰品,基本上是将你的游戏设计和构建成碎片。更多信息
请参阅术语表
分别已加载和卸载。Unity 会引发sceneLoaded事件之后OnEnable但在Start对于场景中的所有对象。有关详细信息和示例使用,请参阅相关的 API 参考页面。

有关将场景加载作为执行流程一部分的关系图,请参阅禁用域和场景重新加载的详细信息

在编辑器启动时运行代码

有时,让部分代码在启动 Unity 编辑器或运行时时立即运行会很有用,无需任何额外的用户作,也不需要代码成为 MonoBehaviour 脚本的一部分。您可以在编辑器启动时运行代码,而无需任何用户作,方法是应用[InitializeOnLoad]属性添加到具有静态构造函数的类。或者,您可以应用[InitializeOnLoadMethod]属性到各个方法。有关更多信息和使用示例,请参阅这些属性的 API 参考。

在运行时初始化时运行代码

您可以通过应用[RuntimeInitializeOnLoadMethodAttribute]到方法。您还可以指定RunTimeInitializeLoadType属性参数来控制属性代码在播放器循环中执行的位置。有关标有此属性的方法的执行顺序的更多信息,请参阅 API 参考RuntimeInitializeOnLoadMethodAttribute.

动画更新循环

图中所示的以下动画循环回调在脚本一段代码,允许您创建自己的组件、触发游戏事件、随时间修改组件属性以及以您喜欢的任何方式响应用户输入。更多信息
请参阅术语表
派生自 MonoBehaviour

在派生自StateMachineBehaviour:

图中显示的其他动画函数是动画系统内部的,并且是为上下文提供的。这些函数具有关联的 Profiler 标记,因此您可以使用分析器帮助您优化游戏的窗口。它显示了在游戏的各个领域花费了多少时间。例如,它可以报告渲染、动画制作或游戏逻辑所花费的时间百分比。更多信息
请参阅术语表
查看 Unity 在帧中何时调用它们。了解 Unity 何时调用这些函数可以帮助您准确了解您调用的事件函数何时执行。有关动画函数和分析器标记的完整执行顺序,请参阅探查器标记放置在代码中,用于描述 CPU 或 GPU 事件,然后显示在 Unity 探查器窗口中。默认添加到 Unity 代码中,或者您可以使用 ProfilerMarker API 添加自己的自定义标记。更多信息
请参阅术语表
.

渲染

此执行顺序仅适用于内置渲染管线。有关执行顺序的详细信息,请参见渲染管线 获取场景内容并将其显示在屏幕上的一系列作。Unity 允许您从预构建的渲染管道中进行选择,或编写自己的渲染管道。更多信息
请参阅术语表
基于可编写脚本的渲染管线,请参阅通用渲染管线高清渲染管线文档的相关部分。如果要在渲染之前立即执行工作,请参阅 Application.onBeforeRender

  • OnPreCull:在相机在场景中创建特定视点图像的组件。输出要么绘制到屏幕上,要么作为纹理捕获。更多信息
    请参阅术语表
    剔除场景。剔除确定哪些对象对摄像机可见。OnPreCull在剔除发生之前调用。
  • OnBecameVisible/OnBecameInvisible:当对象对任何摄像机可见/不可见时调用。OnBecameInvisible不会显示在上面的流程图中,因为对象可能随时变得不可见。
  • OnWillRenderObject:如果对象可见,则为每个摄像机调用一次
  • OnPreRender:在摄像机开始渲染场景之前调用。
  • OnRenderObject:在完成所有常规场景渲染后调用。此时,您可以使用 GL 类或 Graphics.DrawMeshNow 来绘制自定义几何体。
  • OnPostRender:在摄像机完成场景渲染后调用。
  • OnRenderImage:在场景渲染完成后调用,以允许后处理在图像出现在屏幕上之前通过应用滤镜和效果来改善产品视觉效果的过程。你可以使用后期处理效果来模拟物理摄像机和胶片属性,例如泛光和景深。更多信息 后处理, 后处理, 后处理
    术语表中查看
    ,请参阅后期处理效果
  • OnGUI:每帧多次调用以响应 GUI 事件。首先处理 Layout 和 Repaint 事件,然后处理每个输入事件的 Layout 和键盘/鼠标事件。
  • OnDrawGizmos用于绘图Gizmos与场景中的游戏对象关联的图形叠加层,并显示在场景视图中。移动工具等内置场景工具是 Gizmo,您可以使用纹理或脚本创建自定义 Gizmo。某些 Gizmo 仅在选择游戏对象时绘制,而其他 Gizmo 则由编辑器绘制,而不管选择了哪个游戏对象。更多信息
    请参阅术语表
    场景视图您正在创建的世界的交互式视图。您可以使用场景视图来选择和定位场景、角色、摄像机、灯光和所有其他类型的游戏对象。更多信息
    请参阅术语表
    用于可视化目的。

注意OnPreCullOnPreRenderOnPostRenderOnRenderImage 是内置的 Unity 事件函数,在 MonoBehaviour 脚本上调用,但前提是这些脚本与已启用的 Camera 组件附加到同一对象。如果您想接收OnPreCull,OnPreRenderOnPostRender在附加到不同对象的 MonoBehaviour 上,您必须使用等效的委托(注意小写on在名称中)Camera.onPreCullCamera.onPreRenderCamera.onPostRender,如脚本参考相关页面中的代码示例所示。

恢复协程和异步任务

挂起的协程可以在执行序列中的不同点恢复,具体取决于所使用的 yield 指令。例如,使用WaitForEndOfFrameresume 在帧末尾,而那些使用WaitForFixedUpdate在固定更新步骤结束时恢复。有关详细信息,请参阅协程

常规 .NET 任务和异步方法在Update阶段。与协程类似,Unity 的自定义Awaitable课程可以在不同的时间点恢复,具体取决于您在等待时使用的方法。有关更多信息,请参阅使用 Awaitable 类进行异步编程

注意:不保证恢复协程和异步任务之间的确切执行顺序。可等待对象被分组在一起,并按照等待的顺序执行。

将 MonoBehaviours 与实体相结合

使用实体组件系统 (ECS) 时,Unity 会将 ECS 系统组更新合并到 Player 更新循环中。

您可以使用实体系统窗口查看 ECS 系统组相对于完整 Player 循环的更新顺序。有关更多信息,请参阅实体包文档中的更新系统的顺序

局限性

通常,您不能依赖于为不同的游戏对象Unity 场景中的基本对象,可以表示角色、道具、风景、相机、航路点等。游戏对象的功能由附加到它的组件定义。更多信息
请参阅术语表
,除非订单是明确记录或可设置的。

您无法指定为同一 MonoBehaviour 脚本的不同实例调用事件函数的顺序。例如,Update一个 MonoBehaviour 的函数可能会在Update函数,用于另一个游戏对象(包括其自己的父级或子级游戏对象)上的相同 MonoBehaviour。

要配置不同 MonoBehaviour 脚本之间的执行顺序,请参阅脚本执行顺序

其他资源

脚本执行顺序
自定义播放器循环