问题
由于项目无节制地加资源和修改资源,热更经常需要下载较多文件,玩家反馈热更过程容易卡死。
官方文档中关于热更性能这一段也证实这个现象的存在:
复现
测试中发现,即使是骁龙8gen2,在32线程也会偶尔卡,而低端机设置10线程都能卡死。
这种卡死还有一个很恶性的问题,就是热更卡死的时候,如果玩家将游戏退到后台再回来,会发现画面是黑的。虽然这个时候热更还在进行,但玩家多半会直接划掉。
而实际上它只是 ui 卡死,进度条可以卡在一半持续几十秒,然后突然重启并且热更成功。
通过 setVerifyCallback 回调方法打 log 也证实这一现象:即使在 ui 卡死的时候,热更也在后台进行。
解决思路
那么思路就有了,利用验证回调方法,判断当前 ui 状态,如果卡死就把线程调到1,然后再慢慢加线程。
(不直接全程1线程是因为这样太慢,对性能好的机子不友好)
这个方法比较简单粗暴,但是纯 js 端的修改似乎没有判断多线程性能的方法。
这样起码保证了热更界面不长时间卡死,最多顿一下,线程调为1就马上不卡了
// 初始化 AssetsManager 的时候,利用这个接口做卡死校验
this._am.setVerifyCallback((path, asset) => {
let now = new Date().getTime();
if (now - this.lastTime > 1000) {
this.lastTime = this.lastAdd = now;
console.log("检测到渲染线程卡死,调低速度");
this._am.setMaxConcurrentTask(1);
}
return true; // 后面依旧是你自己的验证方法,这里忽略验证
});
/** 记录当前时间戳,用于对比是否线程卡死 */
private lastTime = 0;
/** 上次加线程数的时间 */
private lastAdd = 0;
update() {
this.lastTime = new Date().getTime();
if (this._am && this.lastTime - this.lastAdd > 500) {
this.lastAdd = this.lastTime;
let curTask = this._am.getMaxConcurrentTask();
// 最大线程数根据实际需求修改
if (curTask < 10) this._am.setMaxConcurrentTask(++curTask);
console.log("下载正常,线程数调整为 " + curTask);
}
}