累积经过的时间并运行有界更新
在每个动画回调中,将经过的时间添加到累加器中。虽然累加器至少包含一个步骤,但按恒定间隔(例如 1/60 秒)更新物理并减去该间隔。然后渲染最新的状态。设置每帧的最大追赶步数;否则,长时间的停顿可能会导致大量积压,从而消耗更多时间并加深延迟。明确决定是否删除、限制超额时间或由其他恢复规则处理超额时间。
保持单位一致。如果速度以每秒世界单位来测量,请将其乘以每个模拟更新中的固定步长。不要将相同的速度乘以帧的完整运行时间并执行多个固定更新,否则移动将被计数两次。
在自己的边界处理输入和渲染
在每个模拟步骤采样当前保持的输入,或对一次性操作进行排队,直到某个步骤消耗掉它们。如果在两帧之间发生按键,请确保在下次更新之前它不会丢失。渲染可以在物理状态之间进行插值,而碰撞和评分则使用模拟状态。 MDN 将 requestAnimationFrame 描述为在重绘之前安排的一次性回调,并建议使用其时间戳来计算进度;累加器使用该时间戳来保持更新间隔固定。
测试循环的极限
比较普通帧、模拟慢帧和较长停顿之间的相同短距离运动和碰撞。验证玩家不会穿过薄墙、长时间停顿后获得额外速度或在追赶过程中多次触发碰撞。根据您的预期规则测试暂停和隐藏选项卡返回。如果固定步长循环使模拟稳定,但高速时碰撞仍然丢失,请使用适合运动的碰撞方法,而不是提高渲染频率。
关于固定时间步长游戏物理的常见问题
固定的时间步长能否保证确定性物理?
不会。它使模拟间隔保持一致,但输入时序、数学和碰撞顺序仍然会产生变化。单独控制那些需要重播的测试。
为什么在帧停顿后限制追赶更新?
如果没有限制,追赶可能会独占后面的帧并加剧延迟。选择并测试适合游戏的恢复策略,包括是否可以丢弃模拟时间。
延伸阅读
发现信息过时了? 报告需要更正的内容