如何正确计算时间增量?

use*_*021 3 language-agnostic game-engine game-physics

我正在尝试创建一款具有独立帧速率的游戏,其中myObject以每毫秒一个单位的速度向右移动。但是,我不知道如何deltaTime在这段代码中计算:

var currentTime = 0;
var lastTime = 0;
var deltaTime = 0;

while( play ) {

    // Retrieve the current time
    currentTime = Time.now();            
    deltaTime = currentTime - lastTime;  
    lastTime = currentTime;

    // Move myObject at the rate of one unit per millisecond
    myObject.x += 1 * deltaTime;       
}
Run Code Online (Sandbox Code Playgroud)

假设第一帧花了 30 毫秒,所以deltaTime应该是 30,但它是 0,因为我们只知道帧开始的时间而不是帧结束的时间。然后,在第二帧中花费了 40 毫秒,因此deltaTime是 30,因此myObject.x是 30。但是,经过的时间是 70 毫秒(第一帧中的 30 毫秒 + 第二帧中的 40 毫秒),因此myObject.x应该是 70,而不是 30。

我不是在模拟物理,我只是想myObject相对于经过的时间(而不是帧)移动。

我该如何deltaTime正确计算?

我知道有些游戏引擎的人会使用大量的时间或滴答声,所以他们会提前制作动画。另外,我已经阅读了 Glenn Fiedler关于修复时间步长的文章和许多其他文章,但我仍然感到困惑。

fre*_*dom 6

尝试这个:

float LOW_LIMIT = 0.0167f;          // Keep At/Below 60fps
float HIGH_LIMIT = 0.1f;            // Keep At/Above 10fps

float lastTime = Time.now();

while( play ) {

   float currentTime = Time.now();
   float deltaTime = ( currentTime - lastTime ) / 1000.0f;
   if ( deltaTime < LOW_LIMIT )
      deltaTime = LOW_LIMIT;
   else if ( deltaTime > HIGH_LIMIT )
      deltaTime = HIGH_LIMIT;

   lastTime = currentTime;

   myObject.x += 1000 * deltaTime;     // equivalent to one unit per ms (ie. 1000 per s)
}
Run Code Online (Sandbox Code Playgroud)

这有很多错误,但它更容易说明基本概念。

首先,请注意,您需要lastTime在循环开始之前使用某个值进行初始化。您可以使用较低的值(即 Time.now() - 33),以便第一帧产生所需的增量,或者像我一样使用它(您将看到我们在循环中限制它)。

接下来,您将在每个帧开始时获取当前时间,用它来计算自上次循环以来经过的时间(在该示例的第一次运行时为零)。然后我喜欢将其转换为,因为以“每秒”为单位比“每毫秒”更有意义 - 但请随意删除该/ 1000.0f部分以将其保留为毫秒。

然后您需要将 deltaTime 限制在某个可用范围(例如我使用 10-60fps,但您可以根据需要更改它)。这只是防止循环运行得太快或太慢。HIGH_LIMIT 特别重要,因为它可以防止非常大的增量值,这可能会导致游戏循环中的混乱(稍微不准确比让代码崩溃更好) - LOW_LIMIT 可以防止零(或非常小的)时间步长,这同样可以有问题(特别是对于物理)。

最后,计算完该帧的新deltaTime后,您可以保存当前时间以供下一帧使用。