- Resources不能热更,对资源的更新需要重新打包
- AB可以热更,不需要对整个游戏重新打包,一般是对非代码资源的热更
- HybridCLR或者LUA是对脚本的热更
AB包
【官方文档】概念理解
Unity Documentation - AssetBundle
Unity Documentation - 本机使用 AssetBundle
【基础知识】
CSDN - Unity中AB包详解(超详细,特性,打包,加载,管理器)
AssetBundle热更新完整工作流与知识点解析
不可以包含代码文件:AssetBundle是Unity中用于打包和分发资源的一种文件格式。它是一个包含特定平台非代码资源的存档文件,例如模型、纹理、预制件、音频剪辑,甚至整个场景
可能具有依赖关系:可以在一个AB包引用另一个AB包的东西,可以压缩(便于传输),内含序列化数据或者资源文件(纹理、音频、Prefab乃至场景等二进制数据块,加载他们是在Unity的另一个线程进行的)
用于动态加载:动态加载的资源打AB包,非动态加载的资源不用打。什么是动态加载?是指在游戏运行时根据需要从外部加载资源,而不是在游戏启动时将所有资源都加载到内存中。所以粗略划分来讲从loading到进入游戏到主界面这个流程以外的东西都可以动态加载。
压缩是可选的:默认是压缩的,但是可以不压缩。压缩减少网络占用(但是解压也耗时间和计算资源),不压缩就加载快(不用解压嘛)。默认压缩是LZMA,但是也支持LZ4。LZ4是块压缩,LZMA是字典压缩(基于Lempel-Ziv算法和马尔可夫链,把数据看做流)
AB文件构成
AssetBundle文件构成:
- 清单(Manifest):清单文件包含了AssetBundle的元数据信息,如依赖关系、哈希值和变体数据。它的作用在于帮助管理AssetBundle之间的依赖关系,以及确保正确的资源加载和版本控制。
- 包体(Bundle)本身组成:实际包含资源的文件,例如模型、纹理、预制件等。
- 变体(Variant)配置文件:指定不同平台或设备上的资源变体,以便在不同环境下提供最佳的性能和用户体验。
AB的载入
载入:下载+加载
AB包的使用分两种情况,一是本地直接LoadFromFile
,二是UnityWebRequestAssetBundle
从指定URL下载,然后按照下面的方法读取其中资源使用:
// LoadAsset<T>(string)会把资源转换为T类型 // 例如下面函数从叫做bundl的AB包中加载名为"myObject"的资源 GameObject obj = bundle.LoadAsset<GameObject>("myObject");
AB卸载
AssetBundle的卸载使用.Unload(bool)
,需要注意的是传入的bool对应两种卸载策略
AssetBundle.Unload(true)
卸载从 AssetBundle 加载的所有游戏对象(及其依赖项)。这不包括复制的游戏对象(例如实例化的游戏对象),因为它们不再属于 AssetBundle。
如果应用程序必须使用 AssetBundle.Unload(false)
,则只能以两种方式卸载单个对象:
- 在场景和代码中消除对不需要的对象的所有引用。完成此操作后,调用
Resources.UnloadUnusedAssets
。 - 以非附加方式加载场景。这样会销毁当前场景中的所有对象并自动调用
Resources.UnloadUnusedAssets
。
Resources.UnloadUnusedAssets
并不是专门针对 “Resources” 文件夹的内容,而是针对在内存中加载的所有资源。
其它
StreamingAssets与AB
官方文档:Unity Documentation - StreamingAssets
CSDN - 详解Unity中的StreamingAssets文件夹
Unity中的StreamingAssets文件夹通常用于存放需要在运行时动态加载的资源文件,事实上StreamingAssets文件夹和Resource文件夹在打包时都会原封不动地加入游戏包中。
StreamingAssets:流媒体资源,典型的例子是视频,不是一直用得到,也没必要一直放在内存中,需要时加载就行
Resources是压缩且加密的,StreamingAsset是原封不动的不作任何处理的。
特点:
- 需要时加载
- 可替换(替换文件名字和被替换的一样就行了)
- 内容不会被压缩(Resource会压缩)
- 不同平台路径不同
- 适合放流式文件(二进制文件)
AB包打包时涉及到这个文件夹(一般会有Copy to StreamingAsset选项),这是显而易见的,把AB放在这里可以满足动态加载的需要
Resource和AB区别
Unity Blog - Asset Bundles vs. Resources: A Memory Showdown
Unity Learn - Assets, Resources and AssetBundles
Unity 资源加载的两种方式:Resources和AssetBundle最详细的解析
使用Resources.Load
方法从Resource文件夹里加载。Resource会将Resource文件夹的所有资源打包到安装包中(相应地,包体增大)。但是运行游戏时,这个文件夹并不是全部加载的,而是按需通过Resources.Load
加载,但是Resources.Load
加载的资源会一直存在于内存中(可以手动卸载)
AssetBundle允许按需加载和动态加载资源,可以根据需要进行资源的加载和卸载,从而降低内存占用。
重复与忽略:
- 在 Unity 中,如果将资源打包到 AssetBundle(AB包)中,那么这些资源将会在构建时从项目中单独复制一份,而不是与项目中原始的资源文件共享。
- Resources 目录下的资源在构建 AssetBundle 时会被忽略,而不会被包含在 AssetBundle 中。不要在Resources下存放直接打包进AB的东西,不过AB包的资源可以引用Resources的资源
AA与AB
CSDN - 【游戏开发探究】Unity Addressables资源管理方式用起来太爽了,资源打包、加载、热更变得如此轻松(Addressable Asset System | 简称AA)
AA底层也是AB(能够轻松逆向),但是中国版AA多了加密功能
热更流程
- 资源部署到原创服务器上
- 客户端检查更新:客户端启动时,首先向服务器发送请求,检查是否有新的AssetBundle版本可供更新。
- 下载更新:如果服务器上存在新版本的AssetBundle,客户端会下载这些更新的AssetBundle文件到本地存储,通常是将更新的 AssetBundle 文件下载到持久化数据路径中,然后再进行加载和应用。
- 更新本地清单:客户端会更新本地的AssetBundle清单文件,记录最新的AssetBundle版本信息和哈希值等元数据。
- 应用更新:客户端使用新的AssetBundle中的资源来更新游戏内容,例如替换旧的模型、纹理或其他资源。不过如果是在游戏进行中未必需要立即应用更新(如果不是立马需要的话,因为占IO)
- 重启或刷新:在完成更新后,客户端可能需要重启或者刷新游戏内容,以确保新的资源得到正确加载和应用。
实际开发时还要提高容错性:考虑到网络异常、更新失败的处理、版本兼容性等问题,以确保热更新的流程稳定可靠。
补充:
- 下载完热更包需要本地资源校对(计算MD5和清单中的比较)
关于下载部署完热更的选择:资源校对通过后不一定跳转到Launch场景,也可能是去重启游戏
关于判断是否需要热更
- 版本号分为大版本号和热更新版本号,大版本号不同就不用比对清单了,直接热更
结合上述两节谈内存优化
针对内存占用较高的情况,可以采取以下优化措施:
- 使用AssetBundle进行资源管理: 将大部分资源打包成AssetBundle,并在运行时按需加载和卸载,以降低初始内存占用。
- 资源共享: 合理设计资源的共享机制,避免重复加载相同的资源,减小内存占用。
- 异步加载: 使用异步加载资源的方式,避免在主线程同步加载大量资源导致内存占用过高。
- 资源释放: 及时释放不再需要的资源,避免资源长时间占用内存。
- 动态加载: 对于大型场景或地图,可以采用动态加载的方式,根据玩家位置或需求动态加载和卸载场景资源,减小内存占用。
- 内存优化工具: 使用Unity内置的Memory Profiler等工具进行内存优化分析,找出内存占用较高的原因,并进行针对性的优化。
要指出的是资源压缩只是减少磁盘空间占用,而且还得额外耗费CPU资源解压,解压之后还和原先占用的内存是一样的
第五点说的动态加载得是AB包方式,因为如果是Resource方式,即便是动态加载,资源确实会一直存在内存中