【技术分享】Creator优化心得:减少脚本文件的大小

首先得说明,我们做的是原生版的手游,所以下面的优化只对原生版有用。

众所周知,当前的Creator不管是调试还是打包,都会将脚本先打包成一个大文件。这对于小型一点游戏项目没有太大问题,一旦代码以万行计,问题就各种暴露出来了:

  • 首担其冲是开发时的编译,我们目前的脚本是11万行左右,改一下代码,基本上需要编译20秒以上。
  • 其次是程序在手机中的启动时间,编译成jsc后,大概是5M左右,JS要加载这5M脚本,还是需要一些时间的。
  • 最后是热更新大小,5M的文件压缩之后,差不多是1.7M左右,也即是每次的热更最小需要这么大小。

我原来的想法是将策划的配置表设置为插件的方式,这样大约可以减少一半的代码行,不知道你对这个数据的感觉如何,对于一个长线的MMO来说,5万行配置数据是很正常的。但是看了官方文档,说插件会在脚本启动前一次性加载,而配置文件大概有200多个,这在安卓上可能会很恐怖的。我还真就编译了一个配置数据是插件的安卓包试过,结果启动时间是10秒左右,而且内存暴涨。从这个例子也侧面证明安卓的IO速度真是出了名的慢,因为这个限制,也没去深入研究,只好作罢。

今天经由@panda的提醒,才知道插件是可以不用一次性加载的,在打包出来的main.js中有:

var jsList = _CCSettings.jsList

这样的代码,jsList里面就包含着插件的脚本文件,我只需要在打包过程中,修改main.js文件,将配置表的插件文件从jsList中删除,那么配置表就不会被预先加载了,代码类似这样:

var jsList = _CCSettings.jsList
if (jsList) {
	for (var i = jsList.length-1; i >= 0; --i) {
		if (isConfigFile(jsList[i])) {		// 这是个伪函数,用来判断是不是配置表的
			jsList.splice(i, 1);
		}
	}
}

这里先解答点疑问,为什么不将配置文件存为json,在程序中要用再去加载。原因是Creator加载数据都是异步的,这意味着,我每次需要数据的时候,都需要用回调函数的方式,这会很麻烦的。

回到上面,作为插件的配置数据,就不能用require简单的取了,我写了一个函数,必须通过这个函数去取配置表:

window.requireConfig = function(configName) {
	if (!window[configName] && cc.sys.isNative && cc.sys.isMobile) {
		require("src/assets/Script/Config/" + configName + '.js')
	}
	return window[configName];
}

当插件未加载,并且是手机的原生版,就调用require去加载插件,注意里面的路径。插件加载完后,会保存为全局变量,所以如果全局变量已经存在,就直接返回了。关于插件的一些限制,可以看看官方文档

从上面可知,其他平台插件是会先加载的,由于我们做的是手游,其他平台只作为开发调试之用,所以就不管了。

我索性把上面的脚本也当作一个插件,这样无论在哪里,都可以用下面的代码获取配置数据:

var mapCfg = requireConfig("MapConfig")
console.log(mapCfg.name)

另一个值得提的地方,是requireConfig尽量在函数中调用,不要像require那样放在模块头,这样可以尽可能的延迟插件的加载。我统计过,在没有做这个处理之前,手机启动到登陆界面,一共加载了65个配置脚本。做了处理后,只加载了5个。这对于手机的启动速度也是非常有好处的。

经过上面的优化之后,脚本行数降到5万多行,编译时间降为8秒。project.jsc经过压缩后变成400多K。在一台千元加的安卓上,从启动到进入LOGO界面,大概只要1.7秒时间:)

在这里真要感谢@panda,和引擎的人做朋友真好,一句话胜读千行代码。另外,1.6新引擎版本的Creator我也试用了,过段时间再发一些体验心得。

16赞

1.6版本都已经做好了么?还是说只是部分功能而已?如果只是部分功能,有没有动态加载资源模块的功能了啊?

就Alpha版本,里面只针对JS引擎的升级。

动态加载资源模块?资源不是一直可以动态加载吗?

很棒的分享,不过我个人还是觉得 json 更简单,异步就异步。

我需要单纯控制只下载一个音乐文件,下载下来后播放,现在的creator可以控制单独下载这一个文件下来,但是好像用不了,1.6的资源模块就方便了,我直接单独下载需要的整个关卡

window.XXX,原生平台也能用?
用插件脚本做配置,也是脑洞大开。省掉了读取解析配置这一步

思路不错,lua文件做配置也有类似问题。这个延迟加载是缓解了,如果总量太多也是没辙,只能怼策划去了:expressionless:。如果热更下来的文件太多,还会有句柄的限制

JSON文本加载不就好了吗

1.6可以这样?那太好了!以后做游戏都做成资源模块就可以了,既可以发布到自己的APP里,也可以发布到别人的APP里。感觉是开启了一扇大门。现在ios也允许加载H5游戏了,不就是这样一个一个的资源模块哇?
我觉得如果cocos creator再提供一个查询引擎版本的接口,API接口保持向上兼容,就像安卓的APP一样了,就牛叉了,资源模块只需要指定自己需要的最低引擎版本。

其实这个功能是我猜想的:joy:,如果不这样的话,我感觉这个资源模块就没有多大用了。以前用cocos2djs版本的时候我们都是可以对资源文件和代码随意下载随意用的,现在creator不能这样用了,如果资源模块不能解决这个问题的话,那资源模块有啥用呢?:mask:

其实我们的配置文件,已经可以认为是逻辑的一部分,在各个系统的很多方面都甩给策划去配。
这样就决定了脚本里会非常依赖于这些配置,把它们当成脚本的一部分是比较方便的。
:))

配置文件可以使用protobuf,序列化之后的message要比json小很多.

以后会用到,标记一下

4321

mark

mark一下,感谢分享