在今天这个快乐周五的早上,Cocos引擎组收到了一些 CP 的紧急反馈,在 iOS 14 上,H5 游戏的性能下降,线上项目受到严重影响。
经过验证,此问题波及 iOS 14 上的所有浏览器、WebView 运行环境,小游戏和原生游戏不受影响。引擎组立即着手调试,经过一天的排查,发现这个问题的症结在 vb 和 ib 的共享上。
为优化性能,Creator 多个 drawcall 之间会共享同一份 vb 和 ib,每个 drawcall 使用一个偏移值在共享 vb 和 ib 中找到本次渲染的数据,但是经过我们验证后发现,共享 vb 和 ib 会导致在 iOS 14 上性能下降非常严重。
![](https://img6.php1.cn/3cdc5/9b0d/ae9/fe58af581c3a2152.png)
所以修复此问题的关键就是,在提交 drawcall 之后,切换 vb 和 ib。经过修改,问题就能得到完全解决。
解决方案:
> 2.2 版本:
在项目脚本最外层加入如下代码,直接覆盖 cc.MeshBuffer 中的方法即可。
const isIOS14Device = cc.sys.os === cc.sys.OS_IOS && cc.sys.isBrowser && cc.sys.isMobile && /iPhone OS 14/.test(window.navigator.userAgent);
if (isIOS14Device) {cc.MeshBuffer.prototype.checkAndSwitchBuffer = function (vertexCount) {if (this.vertexOffset + vertexCount > 65535) {this.uploadData();this._batcher._flush();}};cc.MeshBuffer.prototype.forwardIndiceStartToOffset = function () {this.uploadData();this.switchBuffer();};
}
也可以自定义引擎,手动合并此PR:https://github.com/cocos-creator/engine/pull/7415 。
2.1.x 版本
原理和 2.2 一样,首先在项目脚本最外层加入如下代码,直接覆盖 cc.MeshBuffer 中的方法。
const isIOS14Device = cc.sys.os === cc.sys.OS_IOS && cc.sys.isBrowser && cc.sys.isMobile && /iPhone OS 14/.test(window.navigator.userAgent);
if (isIOS14Device) {cc.MeshBuffer.prototype.checkAndSwitchBuffer = function (vertexCount) {if (this.vertexOffset + vertexCount > 65535) {this.uploadData();this._batcher._flush();}};
}
但 2.1 中没有实现 forwardIndiceStartToOffset,所以你还需要自定义引擎并找到 model-batcher.js,将 _flush 方法中的最后三行改为:
const isIOS14Device &#61; cc.sys.os &#61;&#61;&#61; cc.sys.OS_IOS && cc.sys.isBrowser && cc.sys.isMobile && /iPhone OS 14/.test(window.navigator.userAgent);_flush () {let material &#61; this.material,buffer &#61; this._buffer,indiceStart &#61; buffer.indiceStart,indiceOffset &#61; buffer.indiceOffset,indiceCount &#61; indiceOffset - indiceStart;if (!this.walking || !material || indiceCount <&#61; 0) {return;}let effect &#61; material.effect;if (!effect) return;// Generate ialet ia &#61; this._iaPool.add();ia._vertexBuffer &#61; buffer._vb;ia._indexBuffer &#61; buffer._ib;ia._start &#61; indiceStart;ia._count &#61; indiceCount;// Generate modellet model &#61; this._modelPool.add();this._batchedModels.push(model);model.sortKey &#61; this._sortKey&#43;&#43;;model._cullingMask &#61; this.cullingMask;model.setNode(this.node);model.setEffect(effect, this.customProperties);model.setInputAssembler(ia);this._renderScene.addModel(model);if (isIOS14Device) {buffer.uploadData();buffer.switchBuffer();}else {buffer.byteStart &#61; buffer.byteOffset;buffer.indiceStart &#61; buffer.indiceOffset;buffer.vertexStart &#61; buffer.vertexOffset;}
},
2.0.x 版本
自定义引擎&#xff0c;并用此文件https://forum.cocos.org/uploads/default/original/3X/2/6/2699adeb70a987f69ea2d72a5c5c953279c235dd.zip 覆盖引擎中的 mesh-buffer.js&#xff0c;然后再使用和 2.1.x 版本相同的改动方式修改。
注意&#xff1a;自定义引擎后需要重新编译引擎才能生效。建议合并后&#xff0c;使用不同手机进行全面测试。
对于本次意外给各位开发者朋友带来的困扰&#xff0c;引擎组感到非常抱歉。
性能是 Cocos 永远不变的追求&#xff0c;引擎组大神们会持续关注这个问题&#xff0c;做好后续预案。如在解决过程中遇到困难&#xff0c;你可以点击【阅读原文】进入论坛与引擎组开发人员联系。
最后&#xff0c;非常感谢热心提供反馈的开发者们&#xff0c;也感谢大家的理解与支持&#xff0c;祝大家周末愉快&#xff01;