主要包括以下三个方面

1、资源构建与更新框架

1.1资源版本比对方案(版本号、资源清单、各资源文件版本)

1.2构建时参数设置、摘取、替换、上传逻辑(分段构建,打包机内存不足)

1.3运行时流程设计,成功失败判定,异常情况的处理方案,网络问题、存储空间不足、文件缺失、文件损坏情况的应对

1.4文件校验方案CRC,MD5,文件存在

1.5并发下载与后台静默下载方案

1.6资源扩展包相关方案

1.7覆盖安装相关问题(覆盖安装后的加载位置、顺序,unity版本升级导致的ab版本不同问题、清单问题、依赖问题、spriteatlas问题等)

1.8新资源覆盖已加载的旧资源的情况的处理方案(尽量避免,重启或卸载)

1.9热更理想解决方案(散列文件与补丁包的对比、结合,每个邻近版本制作补丁包,兼容散列下载)

1.10构建AB参数对比

lz4速度快,包体大,内存占用低

lzma包体最小,但内存大,整体解压

Uncompressed包体最大,速度最快

AB构建策略,是否可以统一打lzma,再将待拷入包内的ab每个调用RecompressAssetBundle再拷入,实现包内lz4,CDN上lzma,下载时会自动转存为lz4(实测可行)

具体步骤如下

首先AB构建时构建2份,一份BuildAssetBundleOptions.None对应lzma,一份BuildAssetBundleOptions.ChunkBasedCompression对应lz4,打在两个目录,放在包内的部分从lz4的目录拷贝,cdn的部分从lzma的目录拷贝

然后在运行时,下载完ab之后AssetBundle.RecompressAssetBundleAsync(url, url + ".LZMA", BuildCompression.LZ4Runtime);转格式为lz4或uncompressed,再删掉lzma,lzma压缩率高,可节约30%左右的热更下载时间

https://docs.unity3d.com/2022.3/Documentation/Manual/AssetBundles-Cache.html

 

2、资源加载与卸载框架

2.1AB加载与资源加载对比(同步异步、内存增长情况、卡顿表现)

2.2AB构建策略(大小、多少对比)

2.3资源卸载方式对比,性能对比

 

3、代码资源更新方案

3.1代码热更方案(lua、ifix、hclr)

3.2相关加密技术

3.3代码热更相关逆向技术(assetstudio、ilspy)

https://github.com/icsharpcode/ILSpy/releases/download/v8.2/ILSpy_binaries_8.2.0.7535-x64.zip

 

4.资源加载、实例化(包含取消CancellationToken)、卸载(引用计数)全套方案

4.1对于动态实例化的资源(如prefab),由对象池管理实例化对象,ab.Unload(true)释放资源

假设某个关卡,有3个怪物预制体xyz在同一个目录里,打成一个ab叫monster,monster可会依赖一些材质mat、贴图

对象实例化部分

由对象池实例化怪物对象,每种怪物一个小池子,池子空的时候去加载,记录池子内部(已回收)与外部(未回收)的数量(当所有对象均被回收时可销毁该对象池)

Asset加载卸载部分

ab引用计数由其加载的资源路径以及被引用的ab路径共同维护一个HashSet

从monster中load x,则monster的hashset中加入x,计数1,其材质ab mat的hashset中加入monster,计数1

再从mosnter中load y,则monster的hashset中加入y,计数2, 其材质ab mat的hashset不变,因为去重,仍然计数1

卸载时,对象池销毁,若销毁x,monster-1=1仍大于0不卸载,再卸载y,monster再减一=0触发卸载

任意ab(这里是monster)触发卸载后,其依赖的ab(这里是mat)也会递归的触发计数减一

每个ab都会维护一个hashset对应其直接依赖的ab

总结即每个ab维护一个依赖的ab hashset和一个引用计数hashset

4.2对于动态加载的资源(如texture),由asset的cache管理资源的引用计数,同样使用hashset,计数为0时调用Resources.UnloadAsset(asset)来释放资源,

在释放资源后继续触发ab.hashSet引用计数减一

assetCache的引用计数也由hashSet控制,set中存入其生命周期相关的节点信息(如UI界面的assetpath),界面销毁时统一对动态加载模块assetCache做减一

 

5.ab间循环依赖、循环引用导致无法正确卸载(包括互相引用、三角引用、四角引用等)

举例说明

目录shop中有多个prefab,shopWindow,shopCell,其中shopWindow内引用了activityTab

目录activity中有多个prefab,activityWindow,activityTab,其中activityWindow内引用了shopCell

如果按目录打ab,那么shop.ab与activity.ab就存在循环依赖

以加载shopWindow为例子

shop.ab的hashset中会加入shopWIndow.prefab和activity.ab

activity.ab的hashset中会加入shop.ab

当shopWindow卸载时,shop.ab的hashset中减去shopWIndow.prefab仍剩有activity.ab,count>0导致两个ab均不能卸载

 

解决这个问题可结合以下两个方案

1.需要规避循环依赖,可编写自动化排查工具

依次遍历每个ab的依赖递归查询是否依赖了自身,并把有问题的ab或asset打印出来

2.预制体之间的引用可以改为弱引用

将引用资源的路径信息挂在预制体上,而不是直接拖上去,不引用guid

 

暂列提纲,详细内容待补充