我已经看过这段代码好几次了。
long lastTime = System.nanoTime();
final double ticks = 60D;
double ns = 1000000000 / ticks;
double delta = 0;
上面的代码占用系统时间并将其存储到lastTime
。60个刻度应该等于每秒更新的次数。
while(running){
long now = System.nanoTime();
delta += (now - lastTime) / ns;
lastTime = now;
if(delta >= 1){
tick();
delta--;
}
它取now
并减去lastTime
,然后将其转换为纳秒/60。是否可以保证now
和lastTime
之间的时间差超过60纳米会导致Δ大于或等于每秒160次?我不明白为什么tick();
会每秒运行60次左右。根据我的计算,每次循环运行时,增量都会增加0.0025左右。
它确保tick()方法每秒只执行60次。它被称为delta计时,在整个游戏社区都有引用。使用delta计时的原因是为了使游戏在所有平台上以相同的速率运行。游戏中的物理和动画等内容需要以相同的速度运行,而不考虑系统的速度。如果你有一个慢系统,而游戏不包括delta计时,那么物理会比游戏在快系统上运行时运行得慢。
它的工作原理
-
计算出你想每秒更新多少次,在你的情况下是每秒60次。
-
找到时间函数中内置的语言的分辨率。您的代码使用Java内置的System.nanotime()函数,该函数返回系统运行的纳秒数的长值。
-
每秒有1000000000纳秒,这意味着tick()每次调用的时间差等于1000000000/60。大约是16666666纳秒。这意味着,无论何时调用tick(),程序都将等待16666666纳秒,然后再调用tick。
-
您必须找到当前帧和最后一帧之间的时间(以纳秒为单位)。这个值除以时间步长(16666666)将得到所需时间的小数百分比。如果将这个小数百分比添加到delta变量中,当delta变量>=1时,已经过了1/60秒,这意味着程序现在可以调用tick()。
-
最后从delta变量中减去1。您不将delta变量设置为0的原因是,可能有比1更大的时间步长,并且delta变量将高于1,这意味着下次循环并调用tick()时需要考虑到这一点
我对代码进行了一些注释,以便更清楚地向您展示正在发生的事情。
//Get the system time
long lastTime = System.nanoTime();
//Specify how many seconds there are in a minute as a double
//store as a double cause 60 sec in nanosec is big and store as final so it can't be changed
final double ticks = 60D;
//Set definition of how many ticks per 1000000000 ns or 1 sec
double ns = 1000000000 / ticks;
double delta = 0;
while(running){
//Update the time
long now = System.nanoTime();
//calculate change in time since last known time
delta += (now - lastTime) / ns;
//update last known time
lastTime = now;
//continue while delta is less than or equal to 1
if(delta >= 1){
//Go through one tick
tick();
//decrement delta
delta--;
}
现在我很确定这就是它的作用,但如果不知道tick()是什么,我就不能确定
在不知道tick()
中有什么的情况下,我不能确定,但我猜它也使用60D
来尝试睡眠大约正确的时间?所以:不,没有保证,这就是这个代码要解决的问题。
它说:"如果tick()
睡眠时间少于一个刻度,那么什么都不要做;如果它睡眠时间超过一个刻度或一次刻度"。
据推测,如果勾选时间足够长(例如,80ns,然后是80ns,这意味着第一个循环将勾选时间增加,第二个循环将其增加2),那么最终会有另一个只有40ns增量的循环,从而使一切趋于平衡。