Unity AssetBundle学习笔记

发布于:2023-12-28 ⋅ 阅读:(121) ⋅ 点赞:(0)

目录

基础介绍

动态资源加载

更新和添加内容

打包策略

资源分组

频繁更新的资源

资源压缩

Unload(true)和Unload(false)

Unload(false)

Unload(true)

确定何时卸载

引用计数

场景和状态管理

资源使用频率

内存预算和监控

用户输入和游戏逻辑

处理依赖关系

 依赖管理

使用 AssetBundle Manifest

减少资源依赖的资源管理实战案例

内存占用查看

版本更新处理


基础介绍

Unity 中的 AssetBundles 是一种用于存储和加载各种资源的打包机制。它们允许开发者将游戏资源(如场景、模型、纹理、声音等)打包成一个或多个文件,这些文件可以在游戏运行时动态加载。AssetBundles 主要用于优化资源的管理和减少应用的初始下载大小。

核心概念

  1. 资源打包:AssetBundles 允许将不同的资源打包成一个集合,方便统一管理和加载。

  2. 按需加载:资源可以在需要时动态加载,而不是一开始就加载所有资源,这有助于减少内存使用和启动时间。

  3. 资源更新:使用 AssetBundles 可以在不发布新版本的情况下更新游戏内容,适用于动态内容更新和热更新。

  4. 跨平台:AssetBundles 可以针对不同的平台进行优化和打包,确保资源在各平台上以最优方式使用。

性能优化

  • 减少包大小:合理组织和分配资源到AssetBundles中,以减少每个包的大小。
  • 按需加载:只在需要时加载特定的AssetBundle,避免不必要的内存占用。
  • 缓存管理:合理管理缓存的AssetBundles,以避免重复下载。

注意事项

  • 依赖管理:处理好资源间的依赖关系,避免重复包含相同的资源。
  • 版本控制:在更新AssetBundle时,确保版本兼容性,避免引起错误。
  • 内存管理:注意AssetBundle的内存使用,特别是在移动设备上。

实践应用

  • 动态内容加载:游戏可以动态加载新的关卡、角色、皮肤等,而无需重新下载整个游戏。
  • 热更新和远程资源:AssetBundles 可以从远程服务器下载,实现游戏内容的热更新。

使用 AssetBundles 可以在不发布新游戏版本的情况下更新游戏内容。

动态资源加载

  1. 资源分离:在使用 AssetBundles 时,游戏的资源不是直接嵌入在游戏的主安装包中,而是被打包成一个或多个独立的 AssetBundle 文件。

  2. 远程托管:这些 AssetBundle 文件可以被托管在远程服务器上,而不是用户的设备上。

  3. 按需下载:游戏可以根据需要从远程服务器下载这些 AssetBundle 文件。例如,当玩家进入一个新的游戏关卡时,游戏可以下载包含该关卡资源的 AssetBundle。

更新和添加内容

  1. 更新资源:开发者可以更新服务器上的 AssetBundle 文件,比如修复一个纹理,添加新的声音效果,或者改进一个模型。当游戏下次请求这个 AssetBundle 时,会获取到更新后的版本。

  2. 添加新内容:同样,开发者可以在服务器上添加全新的 AssetBundle 文件来增加游戏内容,比如新的关卡、角色或道具。

  3. 动态加载:当这些更新的或新添加的 AssetBundles 被下载到用户设备上后,游戏可以动态加载这些资源,实现内容的更新或添加。

优势

  • 减少下载大小:初始游戏安装包可以更小,因为不需要包含所有资源。
  • 减少更新频率:减少需要通过应用商店发布的完整游戏更新的频率。
  • 灵活性:允许更加灵活地管理游戏内容和推出新内容。

实际应用

  • 热更新:常用于游戏的热更新,允许快速修复错误或调整游戏平衡。
  • 活动和季节性内容:方便地为游戏添加特殊活动或季节性内容。

打包策略

资源分组

  • 按类别分组:将相似类型的资源分组打包,如将所有纹理放在一个 AssetBundle,所有模型放在另一个。
  • 按用途分组:根据资源在游戏中的使用情景进行分组。例如,一个游戏关卡的所有资源可以打包在一个 AssetBundle 中。

频繁更新的资源

  • 单独打包:将可能会经常更新的资源单独打包,以便在不影响其他内容的情况下更新它们。

资源压缩

  • 选择合适的压缩格式:根据资源类型和平台需求选择合适的压缩格式,以减少 AssetBundle 的大小。

Unload(true)和Unload(false)

Unload(false)

当调用 Unload(false) 时,Unity 会卸载 AssetBundle 对象本身,但不会卸载通过该 AssetBundle 加载进来的任何对象(如纹理、模型、预制件等)。这意味着:

  • 内存保留:已加载的资源(例如通过 AssetBundle 加载的游戏对象和纹理)会保留在内存中。
  • AssetBundle 对象卸载:AssetBundle 的引用被清除,意味着不能再从这个 AssetBundle 加载新的资源。

这种卸载方式适用于那些需要保留已加载资源的场景,例如,如果你已经使用 AssetBundle 中的资源创建了游戏对象,并且希望这些对象在卸载 AssetBundle 后仍然可用。

Unload(true)

调用 Unload(true) 时,Unity 不仅卸载 AssetBundle 对象,还会卸载所有通过该 AssetBundle 加载并实例化的资源。这包括:

  • 内存释放:通过该 AssetBundle 加载的所有资源都将从内存中卸载。
  • 资源不再可用:之前从这个 AssetBundle 加载的所有对象将不再可用,并且如果这些对象还在场景中,它们可能会停止工作或显示为丢失状态。

这种卸载方式适用于需要完全清理资源的情况,例如,当玩家离开某个游戏关卡并且不再需要该关卡资源时。

确定何时卸载

怎么确定什么时候AB包的资源不用了,什么时候进行卸载,使用什么算法

引用计数

引用计数是一种常见方法,用于跟踪资源被多少个对象或系统所引用:

  • 增加引用:当一个对象开始使用某个资源时,该资源的引用计数增加。
  • 减少引用:当对象不再使用该资源时,引用计数减少。
  • 判断卸载:当资源的引用计数降到零时,可以安全地卸载该资源。

场景和状态管理

基于游戏的当前状态或场景来管理资源:

  • 按场景卸载:在场景切换时卸载特定场景相关的资源。
  • 状态机:使用状态机来管理游戏状态,根据不同状态加载和卸载资源。

资源使用频率

分析资源的使用频率和最近使用时间:

  • LRU(Least Recently Used)算法:定期检查资源的最近使用时间,如果某个资源在一定时间内未被使用,则将其标记为可卸载。
  • 使用频率:跟踪资源使用的频率,低频使用的资源可以被优先考虑卸载。

内存预算和监控

设定内存预算并监控实际使用情况:

  • 内存限制:为资源设定内存预算。当接近或超过预算时,开始卸载最不常用的资源。
  • 性能监控:实时监控应用的内存使用情况,当内存使用达到某个阈值时触发资源清理。

用户输入和游戏逻辑

根据用户行为或游戏逻辑来决定资源的加载和卸载:

  • 用户操作:用户进入或退出某个游戏模块时,加载或卸载相关资源。
  • 游戏进度:根据游戏进度和玩家成就来动态管理资源。

处理依赖关系

 依赖管理

  • 处理依赖关系:Unity 允许自动处理 AssetBundle 间的依赖关系。如果一个 AssetBundle 依赖于另一个,则加载时必须先加载它所依赖的那个。
  • 避免重复包含:确保不会有重复资源在多个 AssetBundle 中出现,以减少冗余。

使用 AssetBundle Manifest

  • 生成和使用 Manifest:当你在 Unity 中构建 AssetBundles 时,Unity 会自动生成一个名为 "Manifest" 的文件,其中包含了所有 AssetBundles 及其依赖关系的信息。
  • 读取依赖:在加载任何 AssetBundle 之前,首先加载其 Manifest 文件,并使用它来了解该 AssetBundle 所有的依赖。
  • 按顺序加载依赖:根据 Manifest 提供的信息,先加载所有依赖的 AssetBundles,然后加载目标 AssetBundle。

如果两个包中含有重复的资源,可以将这部分重复的资源单独打成一个包:

点击Move duplicate to new bundle

此时两个原来的包就会依赖于这个新包了

不过依赖关系一般不建议超过三层

将所有角色打包在一个大包里好还是每个角色单独分包好呢?

后者好,因为一方面更新单个角色时可以只更新那一部分,

而且加载小的资源包所花的时间也更短

如果是多个角色打在一个包里,那在加密和解密的时候,需要把其他角色相关的资源也进行解密才能加载出该包,这样也费时间。

unity中 一个AB包只能被加载一次,为了适应这种规则,必须记录哪些包是被加载过的

例如改成下面这样:

减少资源依赖的资源管理实战案例

当游戏中的场景资源依赖于UI和人物资源时,如何管理?

教学源自:06实战!分离依赖和加载(人物,UI)包_哔哩哔哩_bilibili

  1. 减少资源依赖

    • 首先场景直接依赖了UI资源和人物资源包。
    • 采取的策略是将 UI 也划分到一个单独的包中,并为其创建一个专门的目录和 AssetBundle。
  2. 处理人物资源的加载

    • 为了去除场景对人物资源的直接依赖,比如提到使用胶囊体来代表人物位置,并配置生成信息。
    • 通过编辑组件参数来动态生成所需内容,如角色和模型信息。
    • 目的是减少场景与人物资源的直接依赖,通过动态配置和实例化来加载人物。

为了减少场景对人物的依赖,将其替换为胶囊体

分离场景和UI的依赖

  • 删除场景中的UI元素,创建专门的加载对象(Canvas loader)来管理UI加载。
  • 目的是进一步解耦场景和UI的直接依赖关系。

重构资源加载接口

原有的UI资源是存放在Resources下并调用相关的api进行加载的,现在将其打包在AB包里,因此需要对相应的接口做一些重构:

  • 将UI使用的资源从 Resources 文件夹移出,并重新部署这些资源。
  • 修改原有基于 Resources 的资源加载接口,改为从新的加载框架加载。
  • 目的是从 Resources 文件夹中完全解脱出来,改进资源加载机制。

图中内容就是将UI相关的资源往外移

内存占用查看

首先创建场景时勾选下面两个选项

在运行后,按下ctrl+7可以打开profiler

当使用了LoadFile的时候,就会将文件加载出来放在内存中

此时就可以在工具里查看内存的使用情况

simple模式下可以看各类资源的使用情况

detailed模式下可以看到AB包下的每个资源分别占用了多少的内存:

版本更新处理

首先比较服务器上最新的版本号,判断版本号是否一致

如果不一致则进行更新。

在比较文件时往往是只比较配置文件的md5值而不是比较一个一个文件的md5值,原因如下

比较配置文件的 MD5 码是一种实现增量更新的有效方法之一。这是因为配置文件通常相对较小,而且更容易比较和更新。

下面是一种使用配置文件的 MD5 码来实现增量更新的基本步骤:

  1. 生成配置文件的 MD5 哈希值:在每次更新前,生成当前配置文件的 MD5 哈希值,并将其存储在服务器上。

  2. 客户端请求服务器上的配置文件 MD5 值:在游戏启动或定期检查更新时,客户端会向服务器请求最新的配置文件的 MD5 值。

  3. 服务器比较 MD5 值:服务器将客户端请求的 MD5 值与服务器上存储的当前配置文件的 MD5 值进行比较。

  4. 确定是否需要更新:如果客户端的 MD5 值与服务器上的不匹配,那么说明配置文件已经发生了变化,客户端需要下载新的配置文件。

  5. 客户端下载并应用新的配置文件:客户端从服务器下载新的配置文件,并用它替

本文含有隐藏内容,请 开通VIP 后查看

网站公告

今日签到

点亮在社区的每一天
去签到