如果没有良好的资源,这是最难理解的事情之一。它通常是新 Unity 开发人员代码中大多数“初学者错误”的原因。
在我们开始之前:
正如您可能已阅读的文档,您可以理解以下内容。
初始化顺序:
- Awake
- Start
帧顺序:
- Update
- 后期更新
您可以通过转到“编辑”>“项目设置”>“脚本执行顺序”进一步自定义特定脚本的顺序(例如:始终在 PlayerMovement 之前运行 ScoreManager)。
However,这不是 Unity 中发生的事情的完整列表。物理循环、渲染和输入都按此顺序在不同时间发生。需要注意的关键是有 2脚本执行周期。 “框架”(最常见 - 更新)和“固定”(最常见 - 固定更新)。
考虑粗略地浏览一下脚本执行顺序 https://docs.unity3d.com/Manual/ExecutionOrder.html.
有 2 个脚本执行周期意味着什么?简而言之,所有 MonoBehaviour 方法都与这两个周期之一相关联。这些方法只会执行一次逻辑,直到循环完成。换句话说,“PlayerMovement.cs”脚本的 Update 方法只会为每一帧运行一次。您的 OnCollissionStay 对于每个固定周期仅运行一次。
为什么 Unity 有 2 个不同的周期。
固定周期Unity 中的(FixedUpdate)是:
物理不需要渲染精灵或可见的 UI 元素就能够计算是否已击中碰撞体或是否应应用重力。 Unity 分离出特定于物理的数据以有效地执行计算。此外,其中很多都是确定性的。如果您在一帧上从 (0,0) 开始,并且您的刚体在下一帧上移动到 (10,10)(并且您没有传送),我可以合理地假设您移动到了点 (5,5)。这使得 Unity 的物理引擎能够“插入”碰撞和交互。这意味着物理学不需要查看每一帧“动作”来确定是否发生了碰撞。固定周期允许 Unity 独立于帧计算物理并安全地传达这些变化。
帧周期Unity中的(更新)是Unity所有交互的基础。如果没有更新游戏的框架,什么都不会发生。如果帧没有更新,那么浪费 CPU 周期来计算游戏逻辑是没有意义的。这意味着:
需要注意的重要一点:固定循环可能会也可能不会每帧都会发生。在较低的帧速率下,每帧可能会出现多个固定周期。在较高的帧速率下,将出现许多帧,而没有任何固定周期。
这对我的游戏逻辑意味着什么?
在大多数情况下,这两个周期相当协调地工作。最常见的担忧原因如下:
-
尝试使用 Transform 更新游戏对象位置and物理学(即刚体)。您应该尝试仅在 2 个周期之一更新游戏对象位置。如果游戏对象预计会与物体碰撞或与重力等物理相互作用,请使用 Rigidbody.move 或 Rigidbody.velocity。
-
尝试在固定周期中读取输入。由于固定周期每帧可能出现 0-多次,因此输入可能会丢失。如果您在一帧上使用 GetButtonDown() 但 FixCycle 不运行,您将“错过”FixedUpdate 中的输入。通常最好使用布尔值或队列来管理输入和物理系统之间的这种差异。 (就像在Update中设置bool Jump = true,以及当您实际执行物理组件时在FixedUpdate中读取/更新bool Jump)