简介
有时候我们需要固定每秒固定次数更新的功能的时候,例如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过大)导致重复运行次数过多,因此在每帧参与运算之前都会对其进行上限判断。这部分可以根据需要自行删改。
/** 累计时间 */
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() {
}