Assets Bundle 大厅子游戏热更的新姿势!
前言
Cocos Creator 2.4 版本出来很久了,期待了许久的新功能 Asset Bundle 也出来了。论坛上关于 bundle 的帖子很多,但是没有一篇关于 bundle 子游戏更新相关的教程。
今天有空就尝试用了一下,看看是否能做子游戏热更相关的功能,给大厅子游戏模式带来新的姿势。
Asset Bundle
Asset Bundle 是可以按照项目需求将贴图、脚本、场景等资源划分在多个 Asset Bundle 中。
我们在规划项目的时候,就可以把一些公用的东西划分出来,把这些和大厅做为一个模块,然后每个子游戏作为一个单独的模块。这样我们只需要把之前的整包热更新,改成单独除 bundle 之外的大厅模块更新,和更新单个 bundle 模块更新,就可以实现大厅子游戏模式。
这里我新建了一个项目。
项目资源规划如图:
我这里设计的 base 和 resources 为项目的公用模块。base 文件夹下分为 scene,script,texture 分别存放场景脚本和图片资源。
Bundle1 用来存放子游戏的全部资源。
构建之后,看了下生成的资源文件目录:依然是 assets 目录和 src 目录。
而 assets 目录下有 bundle1,main,resources 目录:
Bundle1 里的脚本和资源都被打包到了 assets 的 bundle1 目录了。
之后我修改了 bundle1 中场景和脚本,新增了 prefab,重新打包,此时我的打包选项是没有勾选 Md5 cache 的。
看到只有 bundle1 下的资源发生了变化。这种构建模式下,修改只更新 bundle1 目录的思路是可行的。
然后又尝试了勾选 md5 cache。我只修改了bundle1 里的脚本。
这时候 main.js 和 src 里的 setting.jsc 文件也发生了变化。
原来是 bundle1 里 index.jsc 的 hash 值保存在 src 的 setting.js 里面,而 setting.js 的 hash 值保存在 main.js 里面。也就是说,bundle1 里的资源变化之后,我们之前规划的大厅模块和 main.js 也发生了变化。
所以在不勾选 md5 cache 是的情况下,是可以实现只更新 bundle 目录,来实现子游戏的更新的。
下一步就是修改热更流程。只要能做到大厅更新的时候,只检查 src 目录,和 assets 下的 internal,main,resources 目录就可以了。
尝试修改热更新脚本:
这里有个地方需要注意,改了之后,如果资源是放到 assets 下面,并没有在文件夹里,是不会被更新到的。
再重新弄一个生成热更脚本,来生成对应 bundle1 目录的资源文件。
热更资源文件生成完成,剩下只需要改代码逻辑就好了。
大厅热更可以用之前的逻辑,子游戏 bundle 热更需要修改一下对应目录。
改为:
我这里处理的是放到大厅热更的目录下面,和正常构建是同一个目录的,这样资源就会被找到。
然后更改下子游戏 bundle 热更完之后的流程。不需要重启,只需要派发一个事件给上层,上层收到事件之后再加载 bundle 的内容。
那热更子 bundle 已经可以了,新增 bundle 呢?这里我修改了 bundle1,同时新建了一个 bundle2 目录,里面加了场景、脚本、图片资源。构建,看到资源变化:
只有 bundle1 目录和新增的 bundle2 目录资源发生了变化,没问题。
新增子 bundle 需要在大厅里加入一个入口,同时把 bundle2 的初始 mainfest 热更到大厅资源下就可以了。
什么是初始 mainfest?
就是新建一个文件夹,不要有任何内容,执行热更资源生成脚本,生成的 mainfest。这样第一次热更新 bundle 的时候,就会把全部的资源下载下来。
这时候,我在热更缺出现了问题,然后排查了很久,才发现是热更把热更目录下的 mainfest 文件都强制改名成 project.manifest 了。
翻了下 c++ 源码,AssetsManagerEx.cpp 写死了用 project.manifest,而且是用宏定义的。
这样的话,只有单个子 bundle 热更是没问题的。如果有多个,热更路径就必须放到不同的目录下,或者修改底层的 AssetsManagerEx.cpp 确保每个 bundle 能对应不同的 mainfest 文件。
这个问题后面再研究,起码现在可以确定大厅和子游戏模式是可以实现的。
需要注意地方,bundle 使用完之后需要调用释放方法把 bundle 资源释放掉。这样才能保证下次更新子 bundle 之后加载,使用的资源都是最新的。这边测试,如果不释放,一些资源是不会更新的。这样符合 bundle 的设计思路,动态的加载和释放。
经 jare 大佬指正,释放之后再加载子 bundle 的代码也是不更新的。但是如果是先更新,后加载 bundle 的资源和脚本,是可以实现子 bundle 热更的。所以设计程序的时候要考虑加载之后的游戏就不要再热更了,等下次打开或者调用 restartgame 之后再更新子 bundle。
结语
实现的过程中还有很多步骤没有赘述,源码已经传到 github 上,
地址:https://github.com/zxcvbnm0014/bundle-update
欢迎一起探讨。
感谢作者「creator 小玉米」的创作分享!欢迎分享本文给身边的朋友,也欢迎您在评论区或进入作者原文一起交流!
如果您在使用 Cocos 引擎的过程中,获得了独到的开发心得、见解或是方法,并且乐于分享出来,帮助更多开发者解决技术问题,加速游戏开发效率,期待您与我们联系!