CocosCreator 3.6.3 - 分包方案(基于远程Bundle)
背景:项目是一个开发成熟准备上线的手游,希望出一个缩小首包的apk包做同时测试,根据测试数据决定最终使用分包还是整包的方式推出。
思路:
1、项目的所有Spine资源都放在了resources下,首先要将纯静态引用的Spine资源分离出去。剩下的动态加载资源再根据实际需求放入分包中。
2、调整资源加载的逻辑,先判断资源在哪个bundle,再通过对应的bundle来读取资源。分包分为2个,1个为前期必备的资源,希望玩家体验流程,另一个为后期资源。
3、远程的bundle是需要热更的,因为之前是整包,使用的是apk原生热更方案,要做兼容处理。
实现:
资源的分离和整理
要做2件事,1个是整理静态资源,另1个是分离动态资源。
静态资源的整理采取了最简单的方式,人工一个个去看存放spine的文件夹,查找uuid的使用,看是否是静态引用的,再到代码中搜索看是否是动态加载过的。然后记录该文件夹名,最后通过脚本将它们都移到res(静态资源目录)下。
分离动态资源则是写了一个组件,在项目的动态加载资源代码中添加我的方法,记录动态加载过的资源。首先记录玩家在创建角色前会用到的资源,比如各种音效、图集、选择服务器页面、创角页面等等,这一部分是要在包内的资源,记录至create.json中。再继续操作跑完新手引导,此时动态加载过的资源记录在task.json中,显然task.json的内容是包含create.json的。此时再通过一个脚本来分离动态资源,只处理我想要处理的文件夹,主要是spine和sprite相关的,在这些文件夹中遍历资源,在create.json中的不动;在task.json且不在create.json中的,移动至subPre分包;不在task.json中的,则移动至sub分包。

资源的加载和管理
首先资源的下载,之前已经分成了2个远程Bundle,subPre是希望玩家在进入主场景之前下载完的,sub则是玩家按需加载。
最终定下的方案是远程资源会构建在remote中,其中是零散的文件,供客户端按需远程加载。再通过脚本生成1个压缩包,第一次下载压缩包解压,之后则使用加载零散文件的方式进行更新。

【问题】
1、如何生成subPre.zip?
方案希望的是下载解压之后的资源包,是相当于使用downloader下载的,所以需要模拟AssetManager下载远程资源的过程。
ccc中下载资源是以管线拼接各种处理方法来实现的。看最终的下载部分 resources\resources\3d\engine\platforms\native\engine\jsb-loader.js,这个js文件是适配原生的js代码,会动态替换一些方法。
阅读download() 和 transformUrl(),下载过的资源会记录在cacheManager中,每次实际下载前会根据最终的url判断是否已经下载在本地,本地没有才会实际下载。
再看cacheManager:resources\resources\3d\engine\platforms\native\engine\jsb-cache-manager.js
它是通过cacheList.json这个文件来记录下载过的资源的,其中files字段对象的key为 最终下载的url,value 是 { bundle:bundle名,url:在gamecaches下的相对路径,lastTime:上次使用时间 },相对路径为[bundle名或空]/[时间戳][自增ID][文件后缀],初始化的时候会读这个文件,缓存资源的时候会写该文件。
所以,编写脚本写将remote/subPre中的资源转换为remote/subPre/[缓存格式],缓存格式即为[时间戳][自增ID][文件后缀],同时生成一个cacheList.json记录files信息,在解压之后,把gamecaches/subPre/cacheList.json中的信息添加到gamecaches/cacheList.json中,也同步内存中的cacheManager的cachedFiles字段即可。

2、提高解压速度
项目中subPre.zip的大小在40M左右,使用jszip库来解压读写大概要花20秒,太久了。所以参考了原生引擎AssetsManagerEx.cpp中的解压方法,在其中实现了一个静态方法用于解压zip,解压时间只需1秒左右。
资源的热更
问题是原生使用的搜索路径的方式热更,远程bundle需要使用md5热更,最终实现如下


浙公网安备 33010602011771号