基于 creator2.4.3 assets bundle 大厅子游戏热更的新姿势

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

19赞

刚看群里说,就实现了 大佬

1赞

我刚下载demo运行了下,更新完bundle1(从1.0.0)之后(更新到1.0.7),再去更新bundle2(原本是1.0.0)就会提示已经是最新版了,是因为判断到game-remote-asset\assets下面的project.manifest版本已经是1.0.7,所以直接提示不用更新了吗

是的,是这样的

请问,这里的子游戏和大厅,是 同一个工程么?

是的,同一个工程。

如果子游戏很多,比如200+,这个工程打卡会不会直接卡死呢?这个AssertBundle没有研究过,他是否支持加载其他项目工程呢?

2.4.3是支持的。200+子游戏还是分项目好,需求不一样吧,我没有那么多子游戏的需求,所以没有考虑分项目。

ok,有空我研究一下这个AssetBundle。之前的项目,一直通过修改引擎源码的方式支持加载其他项目,这种侵入的方式,升级引擎比较麻烦。

2赞

AssetBundle 不能删除缓存,一但版本更新多了。前端就是灾难
比较好的就是自己实现下载更新。
自己把Bundle打包成zip下载到客服端本地解压,然后加载本地Bundle
这样还可以跨项目使用

AssetsManager是对比差异更新,会删除热更路径下的旧资源的,不存在你说的这种问题。安装包里的需要删除的资源是肯定删不掉的,但是并没有影响。

其他项目的 asset bundle 是可以加载的,需要注意的是其他项目里面的 main resources internal 这些 bundle

我现在把生成的 main 和 resources 两个 bundle 名字改掉,然后也可以正常使用了

以支持多款子游戏,github以及帖子实现方式都已更新。

mark一下

我现在是用2.4版本,将一个游戏相关的资源放在一个bundle目录下,但这样一个游戏改动了,打包就会全打一遍,游戏多的话,肯定会慢很多,有没有办法只打包指定的bundle文件夹

可以分不同的项目。单个项目做为一个bundle。

我把bundle1配置为了远程包,构建的assets下就没有bundle1了,然后热更bundle1,提示是热更完成,但assets下仍然没有东西,不知道热更到哪里去了

配置远程包就不需要再热更bundle1了。远程包本身就提供热更的功能。

我发现,用了远程包就需要勾选md5 cache,否则不更新
但使用了md5 cache,本地每次都会下新文件,而老的文件还在,那样本地文件岂不是越来越多?