为什么对固定时间步长的游戏循环使用积分? (Gaffer 谈游戏)

Why use integration for a fixed timestep game loop? (Gaffer on Games)

http://gafferongames.com/game-physics/fix-your-timestep/

http://www.koonsolo.com/news/dewitters-gameloop/

在 Glenn Fiedler 的修复你的时间步长! 文章的最后一个游戏循环中,他使用了一个更新循环,将游戏逻辑推进一个固定的增量时间。既然delta时间是固定的,那他为什么要根据delta时间来积分呢?在基于固定时间步长的游戏中,运动不能像这样简单:

if ( keyboard pressing "W" ) {
    velocity += acceleration
}
position += velocity

而不是传递增量时间变量:

if ( keyboard pressing "W" ) {
    velocity += integrated(acceleration, delta_time)
}
position += velocity * delta_time

因为 "fixed" 时间步长循环中的增量时间没有任何意义,就像将所有内容乘以 1。在基于 "variable" 时间步长的游戏中,您必须使用增量时间并积分议案,但在这种情况下,这无关紧要。请注意 delta time 的变量是如何设置为常量且从未更改的,游戏逻辑已经是确定性的,并且您似乎不需要在代码中的任何地方将速度和加速度乘以 delta time。顾名思义,我从这篇文章中得到的是 "Fix Your Timestep!,",因此您拥有确定性的游戏逻辑,而不是浮点不准确和随可变时间步长而来的物理爆炸。我只是对为什么要将增量时间传递给更新函数感到困惑,因为它似乎违背了本文的目的。事实上,这两篇文章都对增量时间提出了相同的论点。

double t = 0.0;
double dt = 0.01;

double currentTime = hires_time_in_seconds();
double accumulator = 0.0;

State previous;
State current;

while ( !quit )
{
    double newTime = time();
    double frameTime = newTime - currentTime;
    if ( frameTime > 0.25 )
        frameTime = 0.25;
    currentTime = newTime;

    accumulator += frameTime;

    while ( accumulator >= dt )
    {
        previousState = currentState;
        integrate( currentState, t, dt ); // integration
        t += dt;
        accumulator -= dt;
    }

    const double alpha = accumulator / dt;

    State state = currentState * alpha + 
    previousState * ( 1.0 - alpha );

    render( state );
}

deWiTTERS 最后一个游戏循环做同样的事情:固定时间步长、插值渲染、渲染跳过。但是它没有像另一个那样提到集成。

他之所以采用更复杂的方式,是为了将物理模拟频率与渲染频率解耦。这样,您可以以可变帧速率(120 FPS、60 FPS 等)渲染,但仍以恒定速率更新游戏逻辑和物理。

这样做的好处之一是,无论 FPS 是多少,游戏逻辑都将表现相同(如果您 运行 在现代计算机上使用许多旧游戏,它们会出现错误,因为它们的物理特性取决于 FPS)。另一个好处是您可以使用集成逻辑在物理模拟步骤之间插入一些额外的帧,从而产生更流畅的动画。

假设加速度随时间线性增加或减少,您可以根据平均加速度改变速度

Δv = (a0 + a1)(Δt)/2

如果游戏包含空气阻力等因素,那么加速度会受到速度^2的影响,通常使用Runge Kutta 4之类的东西来更新每个时间步长的速度变化和位置变化。


我的印象是,大多数基于 PC 的游戏都为物理引擎使用独立的固定频率,理想情况下与帧速率无关。对于这些游戏,即使显示缓慢,如果玩家能够处理视觉效果,实际游戏玩法也是一样的。我见过较早的赛车游戏可以做到这一点,图形性能不会影响物理效果,而较新的赛车游戏可以降低图形设置来提高游戏车的性能,这是一个错误。

Link 示例 Windows 代码 运行 一个线程几乎在任何合理的固定频率下,不随时间漂移。

16.66ms frames times. How do you get a perfect 60 fps when sleep() only goes by whole milliseconds?

在 MSDOS 时代,由于 PC 以 (105/88) Mhz = 1.19318 Mhz 运行计时器,因此游戏将其用作高精度计时器计数器。

一个固定的时间步长,真的应该只用于数学或科学应用。为什么?因为在游戏中,如果您 运行 的帧率为 30fps,那么增量时间大约为 34 毫秒,这意味着需要 34 毫秒来更新上一帧并准备好更新下一帧。所以在大多数应用中,固定时间步长是没有用的。

当谈到物理引擎时,这几乎总是完全取决于您的游戏,但大多数时候,物理引擎在单独的线程上运行,但它仍然需要将增量时间作为参数,正确解决冲突。

增量时间是完成最后一帧所花费的时间。

希望对您有所帮助。