事件函数是一组内置事件,您的 MonoBehaviour 脚本一段代码,允许您创建自己的组件、触发游戏事件、随时间推移修改组件属性并以任何您喜欢的方式响应用户输入。 更多信息
参见 术语表 可以通过实现适当的方法(通常称为回调)来选择性地订阅。回调对应于核心 Unity 子系统(如物理、渲染和用户输入)中的事件,或脚本自身生命周期的各个阶段,例如其创建、激活、依赖帧和不依赖帧的更新以及销毁。当事件发生时,Unity 会在您的脚本上调用关联的回调,让您有机会实现逻辑以响应事件。
在 Unity 触发这些事件并在预定顺序调用关联的 MonoBehaviour 回调的范围内,此处记录了该顺序。了解执行顺序非常重要,这样您就不会尝试使用一个回调来执行依赖于尚未调用的另一个回调的工作。但是,请记住,某些回调用于事件(例如由用户输入触发的事件),这些事件可以在游戏运行期间的任何时间发生。您应结合此页面和 MonoBehaviour 脚本参考(事件回调在其中列在消息下)来全面了解每个事件的含义和限制。
下图总结了 Unity 如何在脚本的生命周期内排序和重复事件函数。
有关各种事件函数的更多信息,请参阅以下部分
下图的范围仅限于您可以通过实现 MonoBehaviour 脚本参考中消息下记录的适当回调,在任何 MonoBehaviour 脚本上订阅的内置事件函数。还显示了一些特定于触发事件的子系统的内部方法以供参考。
除了这些内置事件函数之外,您还可以在脚本中订阅许多其他事件。一些主要类,例如 Application、SceneManager 和 Camera一个组件,在您的场景中创建特定视点的图像。输出要么绘制到屏幕上,要么作为纹理捕获。 更多信息
参见 术语表 提供了您可以向其中注册自己的回调方法的委托。方法属性(如 RuntimeInitializeOnLoadMethodAttribute)也可用于在 场景场景包含游戏环境和菜单。将每个唯一的场景文件视为一个唯一的关卡。在每个场景中,您放置您的环境、障碍物和装饰,本质上是分段设计和构建您的游戏。 更多信息
参见 术语表 的某些阶段执行方法。请参阅您感兴趣的组件或子系统的脚本参考,以查看您可以订阅哪些事件回调以及它们的执行顺序详细信息。
注意:某些浏览器不支持 SVG 图像文件。如果上面的图像显示不正确(例如,如果看不到任何文本),请尝试使用其他浏览器,例如 Google Chrome 或 Mozilla Firefox。
一般来说,您不应该依赖于对不同 游戏对象Unity 场景中的基本对象,可以表示角色、道具、场景、摄像机、路径点等。游戏对象的函数由附加在其上的组件定义。 更多信息
参见 术语表 调用相同事件函数的顺序——除非明确记录或可设置该顺序。如果您需要更细粒度地控制播放器循环,可以使用 PlayerLoop API。
您无法指定对同一 MonoBehaviour 子类的不同实例调用事件函数的顺序。例如,一个 MonoBehaviour 的 Update
函数可能在另一个游戏对象上同一 MonoBehaviour 的 Update
函数之前或之后调用——包括其自身父级或子级游戏对象。
您可以使用 项目设置一系列广泛的设置,允许您配置物理、音频、网络、图形、输入以及项目其他许多方面的行为。 更多信息
参见 术语表 窗口的 脚本执行顺序 面板来指定一个 MonoBehaviour 子类的事件函数应该在另一个子类的事件函数之前调用。例如,如果您有两个脚本 EngineBehaviour 和 SteeringBehaviour,您可以设置脚本执行顺序,使 EngineBehaviour 始终在 SteeringBehaviour 之前更新。如果 以附加方式加载多个场景,则配置的脚本执行顺序会一次完全应用于一个场景,而不是跨场景部分应用,因此 EngineBehaviour 和 SteeringBehaviour 都将在一个场景上更新,然后才能在下一个场景上更新。
当场景开始时,这些函数会被调用(每个场景中的每个对象调用一次)。
Awake
:当创建对象的新实例时调用的第一个生命周期函数。始终在任何 Start
函数之前调用。如果游戏对象在启动期间处于非活动状态,则 Awake
不会被调用,直到它被激活。OnEnable
:当对象变为启用且活动时调用,始终在 Awake
(在同一对象上)之后以及任何 Start
之前调用。对于作为场景资产一部分的对象,所有脚本的 Awake
和 OnEnable
函数会在任何脚本的 Start
和后续函数调用之前调用。但是,当您在运行时实例化对象时,无法强制执行此操作。
Awake
仅保证在每个单独对象的范围内在 OnEnable
之前被调用。在多个对象之间,顺序是不确定的,您不能依赖一个对象的 Awake
在另一个对象的 OnEnable
之前被调用。任何依赖于场景中所有对象都已调用 Awake
的工作都应在 Start
中完成。
上图中未显示 SceneManager.sceneLoaded 和 SceneManager.sceneUnloaded 事件,它们允许您在场景分别加载和卸载时接收回调。有关详细信息和示例用法,请参阅相关的脚本参考页面。您可以预期在 OnEnable
之后但 Start
之前接收到 sceneLoaded
通知,适用于场景中的所有对象。有关将场景加载作为执行流程的一部分包含在内的图表,请参阅 禁用域和场景重新加载的详细信息。
您还可以使用 RuntimeInitializeOnLoadMethodAttribute 及其类型 BeforeSceneLoad 和 AfterSceneLoad 使您的方法分别在场景加载之前或之后运行。有关使用这些类型标记的方法的执行顺序信息,请参阅 RuntimeInitializeOnLoadMethodAttribute 脚本参考主页。
Reset
:当脚本第一次附加到对象时以及使用重置命令时调用以初始化脚本的属性。OnValidate
:每当设置脚本的属性时调用,包括在对象反序列化时,这可能在各种时间发生,例如当您在编辑器中打开场景以及域重新加载之后。Start
:仅当脚本实例启用时,在第一次帧更新之前调用。对于作为场景资产一部分的对象,Start
函数会在任何脚本的 Update
调用之前对所有脚本调用。但是,当您在游戏过程中实例化对象时,无法强制执行此操作。例如,如果您从另一个对象的 Update
函数实例化对象,则实例化对象的 Start
无法在原始对象的 Update
第一次运行之前被调用。
OnApplicationPause
:在检测到暂停的帧结束时调用,实际上是在正常的帧更新之间。在调用 OnApplicationPause
之后会发出一个额外的帧,以允许游戏显示指示暂停状态的图形。当您跟踪游戏逻辑和交互、动画、摄像机位置等时,您可以使用一些不同的事件。常见的模式是在 Update
函数中执行大部分任务,但您也可以使用其他函数。
FixedUpdate
以游戏时间的固定间隔发生,而不是每帧发生一次。由于这些更新是固定的,并且帧速率是可变的,因此当帧速率很高时,在一帧中可能没有固定的更新,或者当帧速率很低时,每帧可能有多个固定的更新。所有物理计算和更新都发生在 FixedUpdate
之后,并且因为它与帧速率无关,因此在 FixedUpdate
中计算移动时,您不需要将值乘以 Time.deltaTime。固定更新发生的间隔由 Time.fixedDeltaTime 定义,可以在脚本中或通过编辑器中的固定时间步长一个可自定义的与帧速率无关的间隔,用于决定何时执行物理计算和 FixedUpdate() 事件。 更多信息
参见 术语表 属性(在编辑器的 时间设置 中)直接设置。有关更多信息,包括用于确定是否执行 Update
或 FixedUpdate
的时间计算,请参阅 时间。
Update
每帧调用一次,是帧更新的主要函数。
LateUpdate
每帧调用一次,在 Update
完成后调用。当 LateUpdate
开始时,在 Update
中执行的任何计算都将完成。LateUpdate
的常见用途是跟随第三人称摄像机。如果您在 Update
中使角色移动和转向,则可以在 LateUpdate
中执行所有摄像机移动和旋转计算。这将确保角色在摄像机跟踪其位置之前已完全移动。
上面 流程图 中显示的以下动画循环回调将在派生自 MonoBehaviour 的脚本上调用
从继承自StateMachineBehaviour的脚本中调用其他与动画相关的事件函数。
有关这些回调的含义和限制,请参阅相关的脚本参考页面。
流程图中显示的其他动画函数是动画系统内部的,用于提供上下文。这些函数具有关联的 Profiler 标记,因此您可以使用Profiler一个帮助您优化游戏的窗口。它显示在游戏的各个领域花费了多少时间。例如,它可以报告渲染、动画或游戏逻辑中花费的时间百分比。 更多信息
参见词汇表查看 Unity 何时在帧中调用它们。了解 Unity 何时调用这些函数可以帮助您准确了解您调用的事件函数何时执行。有关动画函数和 Profiler 标记的完整执行顺序,请参阅Profiler 标记放置在代码中以描述随后在 Unity Profiler 窗口中显示的 CPU 或 GPU 事件。默认情况下添加到 Unity 代码中,或者您可以使用ProfilerMarker API添加您自己的自定义标记。 更多信息
参见词汇表。
此执行顺序仅适用于内置渲染管线。有关基于可脚本化渲染管线的渲染管线一系列操作,用于获取场景的内容并在屏幕上显示。Unity 允许您从预建的渲染管线中选择,或编写您自己的渲染管线。 更多信息
参见词汇表中的执行顺序的详细信息,请参阅通用渲染管线或高清渲染管线的相关文档部分。如果您想在渲染之前立即执行工作,请参阅Application.onBeforeRender。
OnPreCull
:在相机剔除场景之前调用。剔除确定哪些对象对相机可见。OnPreCull
在剔除发生之前立即调用。OnBecameVisible
/OnBecameInvisible
:当对象对任何相机可见/不可见时调用。OnBecameInvisible
未在上面的流程图中显示,因为对象可能随时变得不可见。OnWillRenderObject
:如果对象可见,则针对每个相机调用一次。OnPreRender
:在相机开始渲染场景之前调用。OnRenderObject
:在完成所有常规场景渲染后调用。您可以使用GL类或Graphics.DrawMeshNow在此处绘制自定义几何体。OnPostRender
:相机完成渲染场景后调用。OnRenderImage
:在场景渲染完成后调用,以允许对图像进行后期处理在图像显示在屏幕上之前应用滤镜和效果来改善产品视觉效果的过程。例如,您可以使用后期处理效果来模拟物理相机和胶片属性,例如 Bloom 和景深。 更多信息 post processing, postprocessing, postprocessOnGUI
:每帧响应 GUI 事件调用多次。首先处理布局和重绘事件,然后针对每个输入事件处理布局和键盘/鼠标事件。OnDrawGizmos
用于在场景视图一个交互式视图,用于查看您正在创建的世界。您使用场景视图来选择和放置场景、角色、相机、灯光以及所有其他类型的游戏对象。 更多信息
注意:OnPreCull、OnPreRender、OnPostRender和OnRenderImage是内置的 Unity 事件函数,在 MonoBehaviour 脚本上调用,但仅当这些脚本附加到与启用的 Camera 组件相同的对象时。如果您想在附加到不同对象的 MonoBehaviour 上接收等效的 OnPreCull
、OnPreRender
和 OnPostRender
回调,则必须使用等效的委托(请注意名称中的小写 on
)Camera.onPreCull、Camera.onPreRender和Camera.onPostRender,如脚本参考相关页面中的代码示例所示。
正常的协程更新在Update
函数返回后运行。协程是可以挂起其执行(yield
)直到给定的 YieldInstruction 完成的函数。
协程的不同用法
yield
协程将在下一帧所有Update
函数都调用后继续。yield WaitForSeconds
在指定的时间延迟后继续,在帧的所有Update
函数都调用后。yield WaitForFixedUpdate
在所有脚本上都调用完所有FixedUpdate
后继续。如果协程在FixedUpdate
之前产生,则它在当前帧的FixedUpdate
之后恢复。yield WWW
在 WWW 下载完成后继续。yield StartCoroutine
将协程链接起来,以便如果一个假设的协程coroutineA
使用yield StartCoroutine(coroutineB());
启动另一个coroutineB
,那么coroutineA
会暂停并等待coroutineB
完成,然后再继续。有关示例,请参阅MonoBehaviour.StartCoroutine。OnDestroy
:此函数在对象存在的最后一帧的所有帧更新后调用(对象可能响应 Object.Destroy 或在场景关闭时被销毁)。这些函数会在场景中的所有活动对象上被调用
OnApplicationQuit
:在应用程序退出之前,此函数会在所有游戏对象上调用。在编辑器中,当用户停止播放模式时会调用它。OnDisable
:当行为被禁用或变为非活动状态时,会调用此函数。