使用Gulp构建Egret微信小游戏
最近在做手机游戏往微信小游戏移植。我们试图将一个在iOS上能够消耗600M内存、场景中超过10W个gameobject的Unity游戏移植到只允许4M代码包大小、50M资源缓存的微信小游戏平台上。由于原先的项目资源管理没有按照程序制定的标准,也没有TA的存在,这真是个异常艰巨的任务。
目前我们第一步已经将初期60M的资源压缩到了26M还可以继续压缩,似乎所有资源在50M以内似乎比较乐观的。
配合资源压缩的gulp自动构建已经初步搭起来了,下面是一些开发的记录。
项目需求
Egret有两种方式可以导出微信小游戏工程。一种是在EgretLauncher中手动导出。另外一种是使用cli命令egret publish
或egret run
进行编译导出。但是使用命令行工具在导出有bug,不会自动同步EgretWeixinSupport中的文件到导出工程,会使得命令执行失败。同时由于微信小游戏的代码包大小限制,游戏资源必须上传到服务器。这样就需要在构建流程中添加对资源处理的过程。使用EgretLauncher进行导出就无法满足需求。
对于使用命令行构建来说,Egret项目支持扩展cli命令,相关文档在命令行扩展插件。由于Egret项目结构不是标准的npm项目,也就不能直接使用node.js的大量工具和库,所以通过Egret中的scrip进行扩展限制较大。
最后是单独实现了一个基于gulp的项目自动构建,具有如下的Feature:
- 可以通过命令行导出,使用本地资源的版本以及使用服务器资源的版本
- 支持自动将Resource目录下的资源上传到AliyunOSS(可以使用gulp插件实现其他Server解决方案)
- 支持使用TinyPNG对图片资源进行压缩
- 资源处理缓存支持,优化多次构建的时间
Quick Start
环境配置
- 安装Node.js 8.11最新的LTS版本
- 使用
npm i -g gulp
安装gulp - 安装微信开发者工具
- 安装白鹭引擎微信导出库
目录结构说明
由于egret项目在打包时会将项目目录整体添加到tsc的include中,所以不能在改目录下添加gulpfile.js或者是package.json文件。
会导致egret build
命令行出错。所以将gulpfile.js
放在项目工程的上级目录。
1 | Mode LastWriteTime Length Name |
gulp task
gulpfile.js中定义了多个task,使用gulpSeq实现多任务的顺序执行。
主要的两个task为 run_remote
和run
。
run_remote会使用egret build
导出微信小游戏工程,然后将resource目录下的资源处理之后上传到aliyunOSS服务器,最后配置egret项目使用OSS上传的资源地址,并拉起微信开发者工具。
而run直接是导出微信小游戏工程后直接处理资源,最后拉起微信开发者工具。
1 | gulp.task("run_remote", gulpSeq( |
在目录下直接执行 gulp run
和 gulp run_remote
就可以直接执行。
构建开发说明
在实现自动构建时遇到了一些问题,在下面做一些记录。
配置文件
项目目录创建了一个config.json
文件,用于配置gulp的一些参数。
- projectfolder: 定义了当前egret工程目录
- wxappid:会在egret导出wx工程后配置
- projectname: 导出的wx工程的项目名称
- res/compressFolders:配置所有需要进行图片压缩的目录
- ossconf:aliyun OSS配置
- ossconf_cache: 同步OSS时生成的缓存文件路径
- server_rul:微信资源下载的远程路径
1 | { |
同步EgertWeixinSupport到导出的微信工程
由于egret publish的命令行执行会报错,不会自动同步微信导出文件。所以我们要手动将微信项目模板文件导出到projname_wxgame
目录中。
参考gulp.task('wx_copy')
在windows下路径为<username>\AppData\Roaming\EgretLauncher\download\EgretWeixinSupport\
。
在macos中~/Library/Application\ Support/EgretLauncher/download/EgretWeixinSupport
通过命令行启动微信开发者工具
微信开发工具支持命令行启动自动打开项目
<微信开发者工具安装目录>/cli -o <projectpath>
所以需要获取到微信开发者工具的安装路径,在macos中可以直接使用:
/Applications/wechatwebdevtools.app/Contents/Resources/app.nw/bin/cli
。
对于window上来说,用户可能会按照到不同的磁盘和目录。微信开发者工具会将目录写入windows的系统注册表,使用reg query HKEY_LOCAL_MACHINE\\SOFTWARE\\WOW6432Node\\Tencent\\微信web开发者工具
可以获取到微信开发者工具的安装目录。
需要注意的是windows的cmd对于中文是使用gbk编码的而不是utf8,所以需要对调用命令行返回的字符串进行编码的处理。
使用Tiny Png进行图片压缩
微信小游戏对于本地资源只有50m的缓存,也就是说游戏的本地资源文件最多有50M。使用TinyPng最多可以将图片压缩到原始大小的20%。
在搜索了多个gulp-tiny插件之后最后使用gulp-tinypng-nokey
进行图片压缩。
由于该插件没有实现图片缓存,每次构建如果都通过网路获取压缩的图片,需要很长的时候。所以手动实现了图片资源的缓存。考虑后续使用gulp-remember
等插件进行缓存。
1 | gulp.task("res_process_img", () => { |
Json压缩
由于从Unity引擎中导出的动画数据对于浮点数没有进行精度的压缩,转成json文件后这部分会造成部分空间浪费。
可以通过遍历所有json数据文件对浮点数的精度进行压缩。最后20M的json数据减少了6M的大小。
1 | function FixNumber(obj,size){ |
在gulp中,所有的文件流是基于在内存中的虚拟文件系统vinyl。要对文件流进行操作也就需要编写gulp的插件。
具体可以参考:
后续考虑使用Bson对json数据进行压缩,能够更大幅度地减少资源的大小。
Egret使用远程资源与本地资源模式切换
Egret的Res支持从远程读取配置或者是从本地读取资源。我们需要切换不同的资源加载模式,游戏的代码需要根据配置的方式选择相应的加载远,在自动构建的阶段根据调用的命令行进行修改这个配置文件。
然而由于这个配置是控制资源文件的加载所以不能使用Egret的RES进行加载。
所以我们需要使用微信小游戏的资源API先加载这个配置文件,根据配置文件中配置的信息决定Egret引擎加载本地或者是远程的项目资源。
配置文件以及代码如下:
1 | { |
1 | if(cisconf.res.use_remote){ |
GulpFile.js
gulpfile.js可以自行修改使用。