Creator2.4版本出来很久了,期待了很久的新功能asset bundle也出来了。论坛说关于bundle的帖子很多,但是没有一篇关于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文件夹所在的路径,这样project.manifest就会被下载到热更路径下的子bundle路径了。
先修改demo里的BundleUpdateModule.js文件。
把子bundle热更路径换成对应目录。然后修改bundle_version_generator.js的readDir函数。
以及doWork函数:

调整子bundle的热更生成文件目录。这下大厅子游戏模式就完成了。
需要注意地方,bundle使用完之后需要调用释放方法把bundle资源释放掉。这样才能保证下次更新子bundle之后加载,使用的资源都是最新的。这边测试,如果不释放,一些资源是不会更新的。这样符合bundle的设计思路,动态的加载和释放。经jare大佬指正,
释放之后再加载子bundle的代码也是不更新的。但是如果是先更新,后加载bundle的资源和脚本,是可以实现子bundle热更的。所以设计程序的时候要考虑加载之后的游戏就不要再热更了,等下次打开或者调用restartgame之后再更新子bundle。
实现的过程中还有很多步骤没有赘述,源码已经传到github上,
地址:https://github.com/zxcvbnm0014/bundle-update
欢迎一起探讨。
欢迎关注公众号:creator小玉米

或者加入qq群一起交流。群号:1093612606
