Unity3D FixedUpdate VS Update

Unity3D 引擎的 MonoBehaviour 的事件回调的执行顺序如下图所示,我们今天重点讨论 FixedUpdate 和 Update 回调的执行顺序,以及它们的相互关系。

从整体的逻辑架构上,FixedUpdate 属于游戏的物理组件(Physics)部分,在游戏中我们只把物理引擎相关的逻辑放在这里进行处理,通常我们不会把其他的逻辑放在这里处理,这样通常会很耗性能。而 Update 则属于 Game Logic 部分,我们通常会把游戏逻辑相关的代码放在这里进行处理。Update 回调是每一帧都会调用一次,这是固定的。而 FixedUpdate 的被调用次数和帧率的关系比较复杂,可以理解为和帧率没有固定的关系,它可能在一帧中被调用多次,也可能一次也不被调用,这取决于 Fixed Timestamp 以及 Maximum Allowed Timestep 这两个参数的影响。

FixedUpdate 和 Update 处于不同的事件循环中,FixedUpdate 的背后是一个稳定的计时器,每隔 Fixed Timestamp 指定的时间就触发一次 FixedUpdate 。需要注意的是,虽然我们可以改变这个 Fixed Timestamp 的数值 (Time.fixedDeltaTime), 但是并不意味着在这个时间后 FixedUpdate 时间一定会被触发,这个 Fixed Timestamp 只是一个参考值而已。

Time.maximumDeltaTime 这个参数也很有意思,也就是上图中的 Maximum Allowed Timestep ,它是指每一帧的最大的时间间隔是多少。如果游戏已经很卡了,帧率很低,这种情况下物理组件相关的函数(比如 Collider.OnTriggerEnter(Collider) ) 和固定帧率更新的函数(比如 FixedUpdate ) 这样的事件就在这一帧里面不会被触发,防止游戏变的更卡。

但是如果每一帧的时间间隔没有超过这个最大值,而且 Fixed Timestamp 是一个比较小的值(比如 0.02秒),那么在一帧里面,物理组件相关的事件函数和 FixedUpdate 会被调用多次。

所以,如果手机的性能遇到瓶颈时,一个可能的优化点就是调高 Fixed Timestamp 的值,让它在一秒内运行测次数变少,从而减少物理组件和 FixedUpdate 相关的开销。当然这个数值的确定要根据项目的实际情况来定。