微信小游戏开发-打包构建

构建

cocos creator的构建过程相对较快,针对微信小游戏平台,构建结果是生成微信开发工具可用的工程文件,典型的构建配置如下:

相对应的脚本指令也很简单:

1
2
3
rd /Q /S .\build\wechatgame
echo 开始构建Release版本
CocosCreator --path ./ --build "debug=false;buildPath=./build"

打包

由于微信小游戏主包4M的限制,把cocos creator的构建结果直接发布是行不通的(除非把整个安装包控制在4M之内,这个基本做不到,尤其如果加入了开放数据域的话)。所以我们会将大部分的资源文件打包上传到CDN服务器上,只留下资源更新场景。
在游戏启动的时候启动资源更新场景,在资源更新场景里完成游戏资源的下载更新,下载完毕之后进入游戏。

拷贝资源更新场景json文件和图片资源

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
echo 开始取文件
rmdir /Q /S ..\BigTank2WXProj\res
mkdir ..\BigTank2WXProj\res

echo 删除project.js settings.js
del ..\BigTank2WXProj\src\project.dev.js /Q
del ..\BigTank2WXProj\src\project.js /Q
del ..\BigTank2WXProj\src\settings.js /Q

echo 拷贝project.js settings.js
xcopy .\build\wechatgame\src\*.js ..\BigTank2WXProj\src\ /Y
xcopy .\buildConfig\Version.js ..\BigTank2WXProj\ /Y
xcopy .\buildConfig\cdn_enable_true\gamesettingconfig.js ..\BigTank2WXProj\ /Y

echo 启动场景json文件,可能会变化,请手动修改
xcopy .\build\wechatgame\res\import\03\0356d831d.json ..\BigTank2WXProj\res\import\03\ /Y

echo 拷贝启动场景资源
xcopy .\build\wechatgame\res\raw-internal\image\*.* ..\BigTank2WXProj\res\raw-internal\image\ /Y /E
xcopy .\build\wechatgame\res\raw-assets\Atlas\UI\ResUpdate\*.* ..\BigTank2WXProj\res\raw-assets\Atlas\UI\ResUpdate\ /Y /E
xcopy .\build\wechatgame\res\raw-assets\Sound\studioBg.mp3 ..\BigTank2WXProj\res\raw-assets\Sound\ /Y

先是清理旧的资源,然后拷贝构建生成的project脚本(工程中所有脚本的合并结果)和setting文件(工程中所有资源的配置信息,如果是开放数据域工程,prefab信息也会被写进setting文件),接着拷贝资源更新场景对应的json文件和所引用到资源。

拷贝资源进行打包

打包的思路是使用7z将需要上传的资源文件打成一个或者多个压缩文件,最简单的方法是直接将资源目录原封不动的打包成压缩文件,游戏在下载之后直接解压到手机外存中就可以使用了。
但是这样做有两个缺点:

  • 游戏中存在大量的json文件(prefab等配置文件),如果在解压的时候对所有的json文件一一进行md5校验,会增加进入游戏的时间。
  • 所有的资源文件都打到了一个资源包中,每次资源更新都将会是全量更新,而很多时候可能只是一张图片的更新。

针对这两个问题,我们对打包流程做了优化:

  • 将项目中的所有json文件以key value的形式写到一个大的json文件中。
  • 将项目的资源分成不同的模块,在游戏启动的时候只下载主模块的资源,其他模块的资源在进入相应模块的时候再下载。

第一点主要是遍历资源目录下所有的json文件,把文件写到Merge.json中,其中key使用的是文件原本在资源目录下的相对路径。
第二点需要在项目中先做好目录的划分,如下图

需要分模块下载的模块需要在resources/Modules目录下建立自己的目录。 默认一个目录就是一个模块,上图中Map01和Map02是两个不同的模块。

在工程中划分好目录之后,打包脚本会根据目录将目录打包成不同的压缩包,并在配置文件中写入文件版本号和md5等信息,下面是Map01的部分配置信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
"Modules": {
"Map01":{
"zipFiles":[
{
"digest":"a1dcdc39f74a17da0394c089fc8521c4",
"resFile":"Map01_20180907230230.zip"
}
],
"version":1,
"resMd5s":[
{
"digest":"d3154f2dd1efaa1c3cada2994863ad24",
"resFile":"res/raw-assets/resources/Modules/1003/Atlas/Building0.5.png"
},
{
"digest":"c9cc13410174e03ad078e3ef3f73ea44",
"resFile":"res/raw-assets/resources/Modules/1003/Atlas/BuildingTop0.5.png"
},

游戏中我们使用ModuleMgr 模块负责模块的下载和更新,当调用downloadModule接口的时候 ModuleMgr会根据版本号检查目标模块是否需要更新,如果需要更新则下载替换,否则直接调用success回调。

1
2
3
4
5
6
7
8
9
10
11
12
13
ModuleMgr.downloadModule({
moduleName: 'Map01',
onProcess: function(process) {
EventMgr.emit(window.CustomEvents.ShowProgress, { progress: THIS.percentageBase + process * THIS.percentage });
},
success: function() {
THIS.ExcuteNext();
console.log('===========>UpdatingFile costTime:' + (Date.now() - startTime));
},
fail: function(error) {
console.error('更新失败!', error);
}
});