Unity学习之Addressables可寻址系统
一、Addressables系统
Addressables (简称 AA) 是 Unity 官方推荐的新一代资源管理系统,旨在解决旧版 AssetBundle (简称 AB) 系统的诸多痛点。AA包(Addressables Assets)相比于旧版AB包(Asset Bundle)<都是用于打包的>的优点:
1. 工作流
AA(Addressables): 你只需要在编辑器中将资源标记为 "Addressable",并给它一个唯一的地址(Address)。构建时,Addressables 会自动分析所有标记的资源,处理它们的依赖关系,并构建出优化的资源包和目录文件。整个过程是声明式的,你告诉引擎 “这个东西是可寻址的”,引擎来处理后续所有复杂的打包逻辑。
AB(Asset Bundle): 你需要编写编辑器脚本,手动将一个个资源(或文件夹)打包到指定的 AssetBundle 中,并手动处理它们之间的依赖关系。这是一个命令式的过程,你必须精确地告诉引擎 “把 A 和 B 打包到 C 包里”,“把 C 包依赖的 D 资源打包到 E 包里”。这个过程非常繁琐且容易出错。
上图将资源标记Addressable:
引用标记地址:Assets/Game/Download/DataTable/Sys_Audio.bytes (一般默认或者推荐用地址作为引用标记,当然也可以根据自己需求调整)
资源分组:Default Local Group (默认的分组,我也可以创建新的分组)
AA 将开发者从繁琐的打包脚本中解放出来,极大地提升了开发效率。
2. 依赖管理
AA(Addressables): 这是 AA 最强大的功能。当你加载一个资源(例如,一个引用了材质和纹理的预制体)时,Addressables 会自动分析并加载其所有依赖项,无论这些依赖项被打包在了哪个远端或本地的包里。你无需关心它们的具体位置。
AA包能自动管理依赖关系:当资源1依赖于资源2时,AB包要求先将资源2加载,才能加载资源1;而AA包直接加载资源1,就能自动将依赖的资源2加载进来;
AB(Asset Bundle): 你必须手动追踪所有资源的依赖关系。如果预制体 A 在 AB 包 prefabs
里,它引用的材质 B 在 AB 包 materials
里,那么在加载预制体 A 之前,你必须手动先加载 materials
包。忘记加载依赖包是 AB 开发中最常见的错误之一,会导致资源丢失(pink/purple 材质球)。
结论:AA 从根本上解决了依赖地狱问题,让资源加载变得简单、可靠。
3. 内存管理
AA: Addressables 引入了资源引用计数 (Reference Counting) 机制。当你加载一个资源时,其引用计数加一;当你释放它时(调用 addressables.Release()
),引用计数减一。只有当一个资源的引用计数为零时,Addressables 才会真正地将其从内存中卸载。这有效避免了重复加载和错误释放。
AB: 你需要手动管理 AssetBundle
对象和其中加载的 Object
的生命周期。你需要记住 Instantiate
出来的对象和它的 AssetBundle
是分离的,卸载 AssetBundle
并不会立即销毁场景中的实例。你必须手动调用 Resources.UnloadUnusedAssets()
来清理不再被引用的对象,这个过程复杂且难以控制,容易引发内存泄漏。
结论:AA 的自动引用计数让内存管理变得安全、简单,大大降低了项目的维护成本。
4. 热更新
AA: 热更新是 Addressables 的核心设计目标之一。它内置了 Content Catalog
(内容目录)机制。你可以轻松地将资源发布到本地或远程服务器(如 CDN)。游戏启动时,AA 会自动检查远程目录和本地目录的差异,如果有新版本,就会下载更新的 catalog 和资源包。整个流程对开发者非常友好。
AB: Unity 只提供了底层的 WWW
或 UnityWebRequest
来下载文件。你需要自己实现一套完整的热更新逻辑,包括:版本号管理、资源清单文件(Manifest)的下载与解析、资源包的下载、缓存、校验以及增量更新等。这需要编写大量复杂且容易出错的代码。
结论:AA 开箱即用地提供了生产级的热更新解决方案,而 AB 需要你 “白手起家”。
5. 可寻址方式
AA: 你通过在编辑器中设置的地址 (Address) 或标签 (Label) 来加载资源,例如 Addressables.LoadAssetAsync<GameObject>("Player");
。代码与资源的物理存储路径完全解耦。
AB: 你需要知道资源所在的 AssetBundle
文件的名称和路径,以及资源在该包里的名称,例如 AssetBundle.LoadFromFile("assets/prefabs")
,然后再 LoadAsset<GameObject>("Player")
。如果移动了资源或重命名了 AB 包,代码就会出错。
结论:AA 的寻址方式更灵活、更健壮,提高了代码的可维护性。
二、Addressables分组使用
Addressables使用步骤:
创建资源组 => 将资源加入资源组 => 打包资源 => 加载资源
步骤1:创建新的分组Packed Assets(打开默认的分组Default Local Group),对新分组名称也可以重新命名。
步骤2:将资源加入分组
方式1:我们直接选择某个资源,在属性面板选中addressable, 设置其分组:
方式2:打开addressable分组面板,直接将资源拖到指定的分组即可。
步骤3:可以直接打包build,动态加载资源。
// 2. 使用 async/await 异步加载资源// Addressables.LoadAssetAsync<T> 会返回一个 AsyncOperationHandle<T>// await 会等待加载完成,并直接返回加载到的对象var prefab = await Addressables.LoadAssetAsync<GameObject>(prefabAddress).Task;
三、Addressables面板解析
1. Addressables Group面板
New菜单下两个功能: Packed Assets 与 Blank(no schema)
Packed Assets: 创建默认配置的资源组,它默认已经为我们提供了最常用的配置,满足 90% 以上的通用打包需求。已包含 Content Packing & Loading
和 Content Update Restriction
两个 Schema,配置为最常用的打包方式。
Blank(no schema):创建一个空白的资源组,它不包含任何预设的 “方案”(Schema)。一个新创建的空白组,其 Content Packing & Loading
和 Content Update Restriction
这两个最重要的配置项都是空的。这意味着,这个组目前没有任何打包和加载的规则。你需要手动为它添加和配置这些规则。
Profile:Default
Profile 是 Addressables 中一个极其重要且强大的概念。它允许你为不同的环境(如开发、测试、生产)定义不同的资源加载路径,而无需修改任何代码。
Default: addressables默认配置,默认选中配置
Manage Profiles: 打开addressable配置面板,这里我们自己创建新的配置。
什么是 Profile?: 它是一个键值对的集合,主要定义了两个核心路径:
Local.BuildPath
: 本地资源在构建时的输出目录。
Local.LoadPath
: 游戏在运行时从哪里加载本地资源。
Remote.BuildPath
: 远程资源在构建时的输出目录。
Remote.LoadPath
: 游戏在运行时从哪里加载远程资源(通常是一个 URL,如 CDN 地址)。
Tools菜单项
Inspect System Settings: 在 Inspector 窗口中打开 Addressables 的全局配置文件 AddressableAssetSettings
。
Check for Content Update Restrictions:
这是一个至关重要的诊断工具,专门用于在执行 ** 增量构建(热更新)** 之前,检查你的项目是否违反了更新规则。
它会扫描所有被标记为 Static Content
(静态内容)的资源组。如果它发现这些组中的任何一个资源在上一次构建之后被修改过,它就会在控制台(Console)中报告一个错误。
为什么这个检查如此重要?:
Static Content
的核心原则是:一旦发布,就不能更改。
当你构建项目时,每个资源都会生成一个唯一的哈希值(Hash),并记录在 Content Catalog 中。
如果一个 Static Content
资源被修改了,它的哈希值就会改变。
当旧版本的客户端(没有更新的客户端)尝试加载这个资源时,它会根据旧的 Catalog 去寻找具有旧哈希值的资源,但此时服务器上可能已经是新版本的资源了。这会导致加载失败或资源不匹配,这就是所谓的 “哈希漂移 (Hash Drift)” 问题。
heck for Content Update Restrictions
工具就是为了在构建前捕捉这种错误,强制开发者遵守 Static Content
的规则。
Group View
(组视图) 这个工具用于切换 Groups
面板中资源的显示和排序方式,以帮助你从不同维度分析和管理资源。
Play Mode Script
这是 Addressables 为了加速迭代而设计的一个核心功能。它允许你在进入 Play Mode 时选择不同的资源加载策略。
Use Existing Build (Default): 使用已有的构建。
- 工作方式: 进入 Play Mode 时,编辑器会直接使用你上次通过
Build
按钮生成的构建结果。 - 优点: 模拟了真实的加载流程(从 AssetBundle 加载),结果最准确。
- 缺点: 每次修改了 Addressable 资源后,都必须重新构建才能在 Play Mode 中看到变化,迭代速度慢。
- 适用场景: 最终测试、性能分析。
- 工作方式: 进入 Play Mode 时,编辑器会直接使用你上次通过
Simulate Groups: 模拟组加载。
- 工作方式: 这是开发时最常用的模式。它不会真正去构建 AssetBundle,而是在内存中模拟组的划分和加载过程。资源直接从编辑器数据库中加载。
- 优点: 迭代速度极快。修改资源后无需构建,直接进入 Play Mode 即可看到效果。
- 缺点: 加载路径和性能表现与真实环境有细微差别。
- 适用场景: 日常开发和快速原型验证。
Use Asset Database: 使用资源数据库。
- 工作方式: 完全绕过 Addressables 的分组和打包逻辑,所有资源都像普通资源一样从 Unity 的 Asset Database 中直接加载。
- 优点: 进入 Play Mode 的速度最快。
- 缺点: 完全没有测试到 Addressables 的加载逻辑。
- 适用场景: 仅当你想快速测试与资源加载无关的逻辑时。
- 最佳实践: 在日常开发中,始终将
Play Mode Script
设置为Simulate Groups
,以获得最快的迭代速度。在需要进行最终测试或性能评估时,切换到Use Existing Build
。
Build菜单
New Build > Default Build Script: 完整构建。
- 工作方式: 这是最标准的构建流程。它会分析所有 Addressable 资源,处理依赖关系,并生成所有必要的 AssetBundle 文件和 Content Catalog。
- 适用场景: 项目首次构建、资源结构发生重大变化后,或作为定期的完整构建。
Update a Previous Build: 增量构建。
- 工作方式: 如上所述,这是热更新的核心。它需要一个之前构建的
build folder
作为基线,然后只构建变更过的部分。 - 适用场景: 发布游戏后,进行内容更新时使用。
- 工作方式: 如上所述,这是热更新的核心。它需要一个之前构建的
Clean Build: 与
Tools > Clean Build
功能相同。
2. Addressable Report面板
Report
面板是一个静态分析工具,它提供了关于你的 Addressables 构建的详细统计信息和诊断报告。
- Build Information:
- Build Time: 构建花费的总时间。
- Build Size: 构建出的所有资源文件(AssetBundles、Catalog 等)的总磁盘大小。这是评估你游戏包体和热更新包大小的重要指标。
- Number of Bundles: 生成的 AssetBundle 文件总数。
- Asset Statistics:
- Total Addressable Assets: 被标记为 Addressable 的资源总数。
- Total Unique Assets: 构建过程中处理的独特资源总数(考虑了依赖关系)。这个数字通常大于或等于 Addressable 资源总数。
- Size by Asset Type: 一个饼图,直观地展示了不同类型的资源(如
Texture2D
,Mesh
,AudioClip
,GameObject
等)在总构建大小中所占的比例。这是快速定位资源大小问题的入口。例如,如果Texture2D
占了 70% 的空间,那么你的优化重点就应该是纹理。
包列表 (Bundles List)
这个列表详细展示了每一个生成的 AssetBundle 的信息。
- Bundle Name: AssetBundle 的名称。
- Size: 该 Bundle 的磁盘大小。
- Asset Count: 该 Bundle 中包含的资源对象数量。
- Dependencies: 该 Bundle 依赖的其他 Bundle 的数量。
- Group: 该 Bundle 所属的原始资源组。
3. 详细介绍Addressable Asset Setting
配置Profile文件,默认时Default配置,也可以Manage Profiles自定义新的配置文件。
Send Profiler Events 控制 Addressables 系统是否向 Unity 的 Profiler
(性能分析器) 发送详细的性能事件。
Log Runtime Exceptions 启用此属性以记录资源加载操作期间发生的运行时异常,并将错误信息写入AsyncOperationHandle.OperationException属性。
Catalog 是 Addressables 的核心,它是一个资源清单文件,记录了所有资源的地址、哈希值和物理位置。
Player Version Override 强制为 Catalog 指定一个版本号。如果留空,Addressables 会自动使用项目的 Player Settings
中的版本号。
Compress Local Catalog 启用此属性可将目录构建为压缩的AssetBundle文件。此属性可减小目录的存储空间,但会增加目录的构建和加载时间。
Build Remote Catalog 启用此属性可创建内容目录的副本,以便存储于远程服务器上。用于构建远程目录。启用该属性后,将提供以下选项:Build & Load Paths: Local / Remote / Custom
Update a Previous Build
要使用“更新以前的版本”部分中的属性,必须启用“生成远程目录”属性。
Check for Update Issues 选择是否在更新过程中执行内容更新限制,以及如何处理结果。
Content State Build Path 设置构建默认构建脚本构建的内容状态文件的位置。
Downloads项
Custom certificate handler 设置用于自定义证书处理的类。该列表包含项目中扩展UnityEngine的所有类。网络。证书管理员。
Max Concurrent Web Requests 设置并发web请求的最大数量。系统会将超过此限制的任何请求排队。建议同时下载2到4次,以达到最佳下载速度。
Catalog Download Timeout 设置等待目录文件下载的秒数。如果将其设置为0,则不会超时。
Build项
Build Addressables on Player Build
- Use global Settings (stored in preferences) 使用Unity编辑器首选项中“地址”下指定的值。
- Build Addressables content on Player Build 当编译时始终构建addressable
- Do not Build Addressables content on Player Build 在构建时,切勿构建可寻址内容。如果修改Addressables内容,则必须在构建之前手动重建它。
Ignore Invalid/Unsupported Files in Build 启用此属性可从生成脚本中排除无效或不受支持的文件,而不是中止生成。
Unique Bundle IDs 启用此属性可在每次构建中为捆绑包创建一个唯一的名称。
Contiguous Bundles 若你的资源包是通过 Addressables 1.12.1 或更早版本生成的,禁用此属性可将资源包的变更(差异)降至最低。
Non-Recursive Dependency Calculation 启用此属性,可在资源存在循环依赖时,缩短构建时间并降低运行时内存开销。
Shader Bundle Naming Prefix 选择为 Unity 着色器(Shaders)生成的资源包(Bundle)的命名方式。