背景
一个采用 Cocos Creator 3.4.2
引擎开发的3D游戏,除了主游戏外,还有一个精简版游戏。精简版运行在小游戏平台,功能非常简单,所以要求启动速度一定要快。
首先在Creator项目设置
中仅留下 WebGL 1.0
、基础3D功能
、基础2D功能
、用户界面
、运行状态统计
这几个模块,其它的全部去掉。此时 Reelase 构建后,引擎自身文件cc.js
是 2M 大小,在iPhone7手机上,引擎启动耗时是 0.5秒,这对于一个超轻量的小游戏来说,还是不够轻快。 因此,对Creator引擎源码进行了全面的裁剪和优化,改造后的引擎包体大小是 1.1M,启动耗时为 0.2秒,基本达到了预期。
这里说的
引擎启动耗时
,是从小游戏入口 game.js 的第一行代码开始,到调用application.js
中的cc.director.loadScene(launchScene, ...)
为止。因为此时引擎已准备就绪,开始加载首场景了,而加载场景的耗时主要看资源量,如果场景复杂则耗时久,和引擎自身没多大关系。所以本文把loadScene(launchScene)
定义为引擎启动结束。
要对Creator引擎裁剪优化,首先是自定义引擎。
一 自定义引擎
以 Mac 平台为例,从Creator右上角点击“编辑器”,即可进入引擎目录,进入 resources/3d,里面有 engine 和 engine-native 两个目录,因为我们是小游戏项目,则只需修改 engine 即可。把整个 engine 文件夹复制到另一个目录,然后在 Creator偏好设置
-> 引擎管理器
中把 自定义ts引擎路径
指向自己刚才复制的那个目录,把 使用内置ts引擎
的勾取消。另外还可以把文字前面那个黄色齿轮点亮,代表这个设置存储在项目内,而不是全局。
如下图所示。
提示:
- 如果只修改引擎ts代码,无需自己编译,只要重启Creator编辑器,就会自动编译;
现在可以任意修改引擎源码,并在项目中生效了。
二 分析启动耗时
刚才说了,原始版本引擎的启动耗时约 500ms,那这 500ms 的时间都花在什么上面呢?先看看引擎启动过程中做了哪些事情,主要流程列出如下。
在每个关键处打印出时间,发现标黄色的这几处:import(‘cc.js’)、initBuiltinRes、_initMaterials、loadAssetBundle 耗时较大,其中加载引擎自身文件cc.js
,耗时就超过 200ms ,看来引擎包体是影响启动速度的第一要事。所以首先要减小引擎包体,把不必要模块都删掉。
三 裁剪引擎源码
3.1 先粗删一遍
做这步之前,需要对自己项目的功能非常熟悉,以及对引擎的基本结构有个大致了解。之后操作就比较简单粗旷了,就是到引擎源码目录,把每个子目录和类大概看一遍,按类名搜索,觉得项目用不上的,就把该类和相关引用删掉。有些是整个文件可删除,有些是删除文件中的一部分,配合代码管理神器git
的助力,删除出现问题也可随时回退。
这样一遍过后,引擎包体从 2M 降到了 1.3M。需要注意的是,每一个源码目录下都有个 index.ts
作为索引,删除一个模块后通常还要在 index.ts
中删除相应引用,否则会报错。
值得一提的是,3.x引擎构建时会同时包含glsl1
和glsl3
两个模块,分别对应WebGL 1.0
和WebGL 2.0
,这两模块每个都有 200K 大小,因为我的项目确定只需要WebGL 1.0
就足够,所以直接把glsl3.ts
及相关引用代码删除,这一个操作就减小了 200K。
其它方面,像动态合图、压缩纹理、延迟渲染、部分灯光、平面阴影、模型合批、graphics、bmfont、letterFont、scroll-view、slider、mouse、keyboard等模块都用不上,所以都是整个相关模块删除。
3.2 根据逻辑细删
粗删一遍后,接下来是根据耗时热点,分析代码逻辑进行细删。观察 initBuiltinRes
和 _initMaterials
耗时较久,调试源码发现,引擎默认创建的有些 texture 和 shaer 是用不上的,例如:billboard、graphics、pariticle-gpu等等,所以继续到 effect.ts
和 glsl1.ts
中删除它们的定义。
需要注意,effect.ts
和 glsl1.ts
分别定义了 effect 数组和 shader 数组,这俩兄弟数组是一一对应的关系,所以删除时要在两个ts文件中同时删。这一个操作又减小了 200K,现在引擎包体大小是 1.1M。
3.3 精简wx适配库
最后把wx adapter中不用的模块也去掉,例如:xmldom、video、audio、EditBox等;
最终裁剪掉的模块和相关代码非常多,不再一一列举,所有的如下图所示。
对本次裁剪优化影响较大的几处已标出绿色显示。
四 优化启动逻辑
现在能删的代码都已经删除了,加载 cc.js 已经很快了,但 loadBundle
中加载 main
和 resources
两个 bundle 仍然耗时较长,原因是加载 JSON 文件 比较慢。
4.1 优化JSON读取速度
因为引擎默认采用了异步方式读取 .json 文件,其实 bundle 相关的 .json 很小,只需 1ms 就能读取完成,但因为用了异步,只能被动等待下一个周期返回,这样就至少需要 10~16ms。因此改成了同步方式,这一改动使整个启动至少加快了 50ms。
修改 platforms/minigame/platforms/wechat/wrapper/fs-utils.js 中的 readJson 代码如下:
readJson (filePath, onComplete) {
// 在引擎启动过程中使用同步方式读取JSON,以加快启动速度。启动完成后恢复异步
if (!window.stAfterScene) {
Promise.resolve().then(function() {
var result = fsUtils.readJsonSync(filePath);
if (!(result instanceof Error)) {
onComplete && onComplete(null, result);
}
});
} else {
fsUtils.readFile(filePath, 'utf8', function (err, text) {
var out = null;
if (!err) {
try {
out = JSON.parse(text);
}
catch (e) {
console.warn(`Read json failed: path: ${filePath} message: ${e.message}`);
err = new Error(e.message);
}
}
onComplete && onComplete(err, out);
});
}
}
如上所示,考虑到运行中加载的JSON文件不确定,也许会很大,所以仅针对启动过程做了提速,启动完成后恢复默认的异步。
其中 window.stAfterScene
是我自己定义的变量,在 application.js
的 onGameStarted
方法中进行定义,并没有太大作用,只是标记引擎启动是否结束。示例代码如下:
window.stBeforeScene = new Date().getTime();
cc.director.loadScene(launchScene, null, function () {
window.stAfterScene = new Date().getTime();
....
}
4.2 优化图片读取速度
在引擎读取图片时,会先去检测文件是否存在,然后才是真正读取。因为这两个操作都是异步,所以读取一张图片至少需消耗两个异步时间。
为提升启动速度,我在这里去掉检测操作,改为直接读取,这样读取图片的耗时减少了50%。
修改 platforms/minigame/common/engine/AssetManager.js 中的 doNothing 方法,如下:
function doNothing(content, options, onComplete) {
try {
onComplete(null, content);
} catch (err) {
onComplete(new Error(`file ${content} does not exist!`));
}
// exists(content, (existence) => {
// if (existence) {
// onComplete(null, content);
// } else {
// onComplete(new Error(`file ${content} does not exist!`));
// }
// });
}
五 总结
总结本次优化,是先跟踪启动流程,分析耗时热点,然后做引擎包体裁剪,再针对耗时原因做专门优化。对Cocos Creator 3.4.2引擎裁剪优化的最终成果,是引擎代码量从 2M
减小到 1.1M
,iPhone7真机上,游戏引擎启动耗时从 0.5秒
降到 0.2秒
,其中,加载引擎自身耗时约 0.15秒
。
对小项目来说,对引擎启动速度影响较大的是引擎自身的包体,毕竟Creator3.x是一个3D引擎,功能越强大代码量也越大。但是,游戏启动慢并不等同于引擎启动慢,这需要结合实际项目做具体分析。
其次是异步文件加载,在确信文件资源很小的情况下,改用同步会大大加快启动速度。
以上是对Creator引擎裁剪优化的一些总结,欢迎探讨。
更多文章请访问个人主页:https://www.chuyouxiang.com/