澄清 Update() 和 FixedUpdate() 的使用? Unity2D

Clarifying the use of Update() and FixedUpdate()? Unity2D

所以我知道 FixedUpdate 应该用于物理操作等,但我无法理解什么才算是物理。因此,例如,我通过查看按下的键然后施加力来移动我的角色。目前我正在 Update() 中执行此操作。是否应将此功能移至 FixedUpdate(),因为 addForce 是应用于物理对象(播放器,因为它具有刚体组件)的代码?

但是,如果我确实将此代码移至 fixedUpdate(),那么在该方法中 运行 和 input.GetKey 是否可以?我在某处读到,如果在 FixedUpdate() 中监听输入,输入会被丢弃吗?所以,是的,令人困惑......听起来 Input.GetKey 应该在 Update() 中,当按下一个键时,一个标志被激活。同时,FixedUpdate() 中的功能正在监视要激活的适当标志。这样...这样输入在 Update() 中处理,移动在 FixedUpdate() 中...我理解正确吗?

此外,我正在使用碰撞器和触发器,这些代码是否也位于 FixedUpdate() 中?

如果没有好的资源,这是最难理解的事情之一。它通常是新 Unity 开发人员代码中大多数“初学者错误”的原因。

开始之前:

您可能已经阅读过文档,理解以下内容。

初始化顺序:

  1. 清醒
  2. 开始

帧顺序:

  1. 更新
  2. 延迟更新

您可以通过转到“编辑”>“项目设置”>“脚本执行顺序”进一步自定义特定脚本的顺序(例如:总是 运行 ScoreManager 在 PlayerMovement 之前)。

但是,这并不是 Unity 中发生的事情的完整列表。物理循环、渲染和输入都按此顺序在不同时间发生。需要注意的关键是有 2 个 脚本执行周期 。 “框架”(最常见 - 更新)和“固定”(最常见 - 固定更新)。

考虑粗略浏览一下 Script Execution Order

有 2 个脚本执行周期是什么意思? 简而言之,所有 MonoBehaviour 方法都与这 2 个周期之一相关联。这些方法只会执行一次它们的逻辑,直到循环完成。换句话说,您的“PlayerMovement.cs”脚本的 Update 方法每一帧只会 运行 一次。您的 OnCollissionStay 只会 运行 每个固定周期一次。

为什么 Unity 有 2 个不同的循环。

Unity 中的固定周期 (FixedUpdate) 是:

  • 确定性
  • 基于数学
  • 不依赖渲染

物理不需要呈现精灵或 UI 元素可见就可以计算是否碰撞器已被击中或是否应应用重力。 Unity 分离出特定于物理的数据以高效地执行计算。此外,其中很多是确定性的。如果你在一帧上从 (0,0) 开始,而你的刚体在下一帧移动到 (10,10)(并且你没有传送),我可以合理地假设你移动到点 (5,5)。这允许 Unity 的物理引擎“插入”碰撞和交互。这意味着物理学不需要查看“动作”的每一帧来确定是否发生了碰撞。固定周期允许 Unity 独立于帧计算物理并安全地传达这些变化。

Unity中的

Frame Cycles(更新)是Unity所有交互的基础。没有框架更新游戏,什么都不会发生。如果框架未更新,则浪费 CPU 周期计算游戏逻辑毫无意义。这意味着:

  • 输入绑定到框架
  • 帧周期取决于渲染

需要注意的重要事项:固定循环可能会也可能不会在每一帧出现。在较低的帧速率下,每个帧可能会出现多个固定循环。在更高的帧速率下,许多帧将在没有任何固定周期的情况下出现。

这对我的游戏逻辑意味着什么?

在大多数情况下,这两个周期可以很好地协调工作。最常见的担忧原因如下:

  • 尝试使用变换物理(即刚体)更新游戏对象位置。您应该尝试仅在 2 个周期之一更新 GameObjects 位置。如果 GameObject 预计会与物体发生碰撞或与重力等物理相互作用,请使用 Rigidbody.move 或 Rigidbody.velocity。

  • 正在尝试读取固定周期中的输入。由于固定循环每帧可能出现 0 多次,因此可能会丢失输入。如果您在一帧上使用 GetButtonDown() 但 FixedCycle 没有 运行,您将“错过”FixedUpdate 中的输入。通常最好使用 bool 或队列来管理输入和物理系统之间的这种差异。 (比如在Update中设置一个bool jump = true,实际执行物理组件时reading/updating FixedUpdate中的bool jump)