抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

简介

有时候我们需要固定每秒固定次数更新的功能的时候,例如 Unity 的 FixedUpdate,Laya 本身不提供这样的方法,或许有人用定时器实现,但是定时器不易管理。本项目提供一种基于帧更新的定时更新方法以解决这个问题。

基本原理

每帧更新的时候计算总更新时间,根据总更新时间除以间隔时间获得当前帧需要更新的次数,根据更新次数循环更新。以此我们可以实现和帧率不同的更新频率。

本例设置间隔时间为 50ms,即每秒运行 20 次。如果当前总帧间隔时间小于 50ms 的情况下,_fiexdTimes运行次数为 0,于是当前帧不运行onFixedUpdate,反之运行 n 次。

60fps 的情况下,每三帧间隔时间达到 50ms,运行一次onFixedUpdate

30fps 的情况下,头 2 次每 2 帧间隔时间超过 50ms,运行 1 次,第 3 次开始由于之前保存的时间为 _savedTime = 32 * 2 - 50 + 32 * 2 -50 = 28 ,加上当前帧的 32ms 于是大于 50ms,运行一次。即前 7 帧为 2 帧 2 次后 1 帧 1 次。

10fps 的情况下,每帧间隔 100ms,因此每帧运行两次onFixedUpdate

通过动态平衡每帧需要执行的次数,就能控制每秒执行的总次数不变。

运行的过程中可能会出现单帧运行时间Math.floor(this._fiexdTimes) * this._intervals实际小于间隔时间this._deltaTime的情况,因此增设一个_savedTime来保存未参与运算的时间,同时为了防止保存的时间和帧间隔时间过长(小游戏挂到后台,游戏暂停导致 deltaTime 过大)导致重复运行次数过多,因此在每帧参与运算之前都会对其进行上限判断。这部分可以根据需要自行删改。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
/** 累计时间 */
private _deltaTime = 0;
/** 上一fixed update 剩余时间 */
private _savedTime = 0;
/** fixed update 执行次数 */
private _fiexdTimes = 0;
/** 逻辑帧间隔时间 单位毫秒 50即每秒更新20次*/
private _intervals = 50;

/**
* 固定更新
*/
private fixedUpdate() {
let mark = false;
let curDelta = Laya.timer.delta;
curDelta = curDelta < this._intervals ? curDelta : this._intervals;
//防止出现长时间放置导致的保存时间过长
if (this._savedTime > this._intervals) {
this._savedTime = this._intervals;
}
//累计间隔时间
this._deltaTime += curDelta + this._savedTime;
//更新次数
this._fiexdTimes = this._deltaTime / this._intervals;
for (let i = 1; i < this._fiexdTimes; i++) {
this.onFixedUpdate();
mark = true;
}

if (mark) {
this._savedTime = this._deltaTime - Math.floor(this._fiexdTimes) * this._intervals;
this._deltaTime = 0;
} else {
this._savedTime = 0;
}
}

/**
* 固定更新运行内容
*/
onFixedUpdate() {

}

评论