版本:2.4.10
一 为啥要分帧
一个游戏帧率是60时,每帧分配的执行时间是1秒/60 = 0.016666秒 = 16毫秒。
当这一帧的计算渲染消耗时间超过16毫秒时,就会进行扩帧,例如计算耗时需要50毫秒,那么需要至少4帧进行计算,导致4帧停留在同一个画面上,视觉上游戏就卡顿了。
为了防止卡顿,所以把大量计算分帧执行,例如总耗时需要50毫秒的计算,分到10帧去执行,那么每帧只占用5毫秒的时间,那么就不会导致卡顿。
二 分帧函数
首先获取当前时间,然后执行函数,再次获取当前时间,如果两次时间超过了分配的执行时间,则将函数放到下一帧执行。
FrameExecute.ts:
/**
* 分帧执行
* @author chenkai 2022.9.1
*/
export class FrameExecute extends cc.Component {
//单例
private static _instance: FrameExecute;
public static get ins() {
if (this._instance == null) {
this._instance = new FrameExecute();
}
return this._instance;
}
/**
* 分帧执行
* @param fun 执行函数
* @param target 执行函数对象
* @param start 起始次数 (从0开始,0表示执行第1次)
* @param max 最大执行次数 (例如5则表示函数总共执行5次)
* @param executeTime 分配的执行时间
* @param data 传递数据
* @returns
*/
public execute(fun: Function, target: any, start: number, max: number, executeTime: number, data: any = null) {
//获取开始时间
var startTime = new Date().getTime();
//执行计数
var count = start;
//开始执行函数,如果超过分配的执行时间,则延迟到下一帧执行
for (var i = count; i < max; i++) {
//执行函数
fun.call(target, count, data);
//超过最大执行次数,则退出
count++;
if (count >= max) {
return;
}
//获取消耗时间
var costTime = new Date().getTime() - startTime;
console.log("执行耗时:", costTime);
//消耗时间 > 分配的时间,则延迟到下一帧执行
if (costTime > executeTime) {
console.log("超时,进入下一轮加载")
this.scheduleOnce(() => { this.execute(fun, target, count, max, executeTime, data) });
return;
}
}
}
}
在场景中使用,分帧加载一个物品并显示到场景中
MainScene.ts:
const { ccclass, property } = cc._decorator;
/**
* 分帧测试
* @author chenkai 2022.9.1
*/
@ccclass
export default class FrameLoad extends cc.Component {
@property({ type: cc.Node, tooltip: "item容器" })
content: cc.Node = null;
@property({ type: cc.Node, tooltip: "item" })
item: cc.Node = null
onLoad() {
this.content.removeAllChildren();
FrameExecute.ins.execute(this.loadAsset, this, 0, 50, 1, { name: "数据" });
}
/**
* 加载函数
* @param count 执行次数
* @param data 传递数据
*/
public loadAsset(count, data) {
console.log("执行第n次:", count, data);
var item = cc.instantiate(this.item);
item.parent = this.content;
}
}
显示效果
搜索
复制