一、分包打包后的rpk结构
1.rpk结构说明
分包加载,即把游戏内容按一定规则拆分为几个包,在首次启动时先下载必要的包,这个必要的包我们称为「主包」,主包加载完成后用户即可进入游戏,其他分包可以在游戏运行过程中边玩边下,可以有效缩短用户首次启动耗时,针对包体较大导致加载慢的问题,建议通过分包加载的方式提升加载成功率。
rpk包分为分包rpk包体和普通rpk包体(无分包),rpk包体实际上是一个压缩包文件的形式,其具体结构介绍如下:
1.1 分包rpk包体结构
分包包体中有原整包、主包main.rpk以及开发者自己拆分的各个分包,分包名由开发者自己确定
> com.application.demo.rpk整体压缩包(包名+.rpk)
> -------------- com.application.demo.rpk 原整包(包名+.rpk) (兼容老版本引擎的原整包=分包主包+分包A+分包B)
> -------------- main.rpk 分包主包(main+.rpk)
> -------------- pkgA.rpk pkgA分包(子包名+.rpk)
> -------------- pkgB.rpk pkgB分包(子包名+.rpk)1.2 普通rpk包体(无分包)
不分包的普通包体仅一个整包,包内无上述结构,包内就是被打包工具按照一定规则打入的游戏工程中的文件,与小游戏工程中打包生成临时文件夹build目录中的一致。
2.rpk包体大小说明
| 包体类型 | 包体大小 | 备注 |
| 普通包(无分包) | 包体<4M | 打包后 rpk 只有一个包体 |
| 分包 | 小游戏的整个 RPK 包体(含主包+所有分包)不超过 30M 主包大小不能超过 4M,单个分包不限制大小 |
二、分包配置
分包方式分为使用引擎分包和手动配置分包两种:当所使用的引擎版本已提供稳定的分包能力时,可直接使用引擎分包;若引擎本身不支持分包或对分包结构有自定义需求,则需要采用手动分包方式在 manifest.json 中进行配置。
1.使用引擎分包
unity、cocos、laya几个引擎在导出时可直接分包,具体可以参看各引擎官方使用指引:
- 小游戏分包 | Cocos Creator(大于等于v2.4.x版本)
- Laya小米小游戏分包指南(大于等于2.5.0版本)
- Unity小米插件发布时会默认进行分包,目前默认分包规则为主包无内容,资源全部放在分包中,如用户需要按照自己期望的分包规则进行配置,请参考下面的配置方式,在manifest.json中配置结构,以及按配置组织小游戏工程结构。
2.手动配置分包
若游戏引擎或使用的引擎版本中不支持分包配置,则手动进行分包配置。首先找到小游戏工程中的manifest.json配置文件,在“subpackages”字段中填写分包配置,同时保证root中的路径,和自己小游戏工程中的文件路径一致。
假设小游戏工程目录如下:
├── build 打包时的临时产出
├── dist 存放打包生成的rpk包
│ └── com.xxx.xxx.signed.rpk 小游戏rpk包
├── sign rpk包签名模块
│ └── debug 调试环境
│ ├── certificate.pem 证书文件
│ └── private.pem 私钥文件
│ └── release 线上环境
│ ├── certificate.pem 证书文件
│ └── private.pem 私钥文件
├── logo.png 游戏图标(非必须)
├── sub1 子包目录(非必须)
│ └── main.js 子包入口js
├── sub2.js 子包js(非必须)
├── main.js 游戏入口js
├── manifest.json 项目配置文件,配置游戏图标、包名等
└── package.json Node.js 项目中的核心配置文件,用于描述项目的基本信息、依赖关系、脚本命令等manifest.json中配置如下:
{
......
"subpackages": [ //分包配置
{
"name": "sub1Name", //子包名称
"root": "sub1/" //可以指定一个目录,目录根目录下的 main.js 会作为入口文件
},
{
"name": "sub2Name", //子包名称
"root": "sub2.js" //也可以指定一个 JS 文件
}
]
......
}三、加载分包
1.调用分包加载API加载分包,同时创建一个LoadSubpackageTask对象
LoadSubpackageTask qg.loadSubpackage(Object object)
该接口用于加载游戏子包。注意:主包或子包不能引用未加载的包中的模块。
参数Object说明:
| 属性 | 类型 | 必填 | 说明 |
| name | String | 是 | 分包的名字,需要和分包配置中的值对应,可以是name或者root |
| success | Function | 否 | 接口调用成功的回调函 |
| fail | Function | 否 | 接口调用失败的回调函数 |
| complete | Function | 否 | 接口调用结束的回调函数(无论成功失败都会执行) |
const LoadSubpackageTask = qg.loadSubpackage({
name: 'package-b',
success: function (data) {
console.info('加载分包 package-b 成功')
},
fail: function (err) {
console.info('加载分包 package-b 失败', err)
}
})2.调用API监听分包加载情况
LoadSubpackageTask.onProgressUpdate(Function callback)
该接口用于获取分包加载状态。
回调函数参数字段说明:
| 属性 | 类型 | 说明 |
| progress | Number | 分包下载进度百分比 |
| totalBytesWritten | Number | 已经下载的数据长度,单位 Bytes |
| totalBytesExpectedToWrite | Number | 预期需要下载的数据总长度,单位 Bytes |
function onProgressUpdateCallBack(res){
console.log('package-a 下载进度', res.progress)
console.log('package-a 已经下载的数据长度', res.totalBytesWritten)
console.log('package-a 预期需要下载的数据总长度', res.totalBytesExpectedToWrite)
}
loadTaskA.onProgressUpdate(onProgressUpdateCallBack)3.调用API取消对分包加载情况的监听
LoadSubpackageTask.offProgressUpdate(Function callback)
该接口用于取消监听分包加载进度变化事件,也就是取消上面接口的监听,传入的callback回调函数与LoadSubpackageTask.onProgressUpdate中传入的是同一个。
loadTaskA.offProgressUpdate(onProgressUpdateCallBack)