我试图创建一个具有独立帧速率的游戏,其中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和其他许多人,但我仍感到困惑。
答案 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 ,就可以节省下一帧中使用的当前时间。