如何正确计算时间增量?

时间:2014-10-26 18:49:29

标签: 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;       
}

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

我没有模拟物理,我只是试图相对于经过的时间(而不是帧)移动myObject.x

如何正确计算myObject

我知道有些游戏引擎用户会使用大块时间或打勾,因此他们会提前制作动画。此外,我已经阅读了Glenn Fiedler的article on fixing your timestep和其他许多人,但我仍感到困惑。

1 个答案:

答案 0 :(得分:1)

试试这个:

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)
}

这有很多不足之处,但它可以更容易地说明基本概念。

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

接下来,您将获得每个冻结开始时的当前时间,使用它来计算自上一次循环以来经过的时间(在此次操作的第一次运行时将为零)。然后我喜欢把它转换为,因为它更有意义地工作在&#34;每秒&#34;超过&#34;每毫秒&#34; - 但随意删除/ 1000.0f部分以保持毫秒。

然后,您需要将deltaTime限制为某个可用范围(例如,我使用10-60fps,但您可以根据需要更改此值)。这样可以简单地防止循环运行得太快或太慢。 HIGH_LIMIT特别重要,因为它可以防止非常大的delta值,这可能会导致游戏循环中的混乱(最好是比代码分解时更不准确) - LOW_LIMIT可以防止零(或非常小)的时间步长,这可以是相同的有问题的(尤其是物理学)。

最后,一旦您为此帧计算了新的 deltaTime ,就可以节省下一帧中使用的当前时间。