版本:Unity 6 (6000.0)
语言:英语
通过文件夹将默认预设应用于资源
AssetBundle 工作流程

AssetBundle

AssetBundle 是一个存档文件,包含 Unity 可以在运行时加载的特定平台的非代码资源(例如模型、纹理、预制件、音频剪辑,甚至整个场景)。AssetBundle 可以表达彼此之间的依赖关系;例如,一个 AssetBundle 中的材质可以引用另一个 AssetBundle 中的纹理。为了高效地通过网络交付,您可以根据用例需求选择内置算法(LZMA 和 LZ4)压缩 AssetBundle。

AssetBundle 可用于可下载内容 (DLC)、减少初始安装大小、加载针对最终用户平台优化的资源以及减少运行时内存压力。

为任何独立平台构建的 AssetBundle 只能在该平台上加载。例如,在 iOS 上构建的包与 Android 不兼容。造成这种情况的原因之一是,着色器在 GPU 上运行的程序。 更多信息
参见 术语表
、纹理和其他类型的数据根据 BuildTarget 构建为特定平台的格式。

当您构建或重建 AssetBundle 时,通常会使用单个 API 调用一起构建项目的所有 AssetBundle。通常最好不要单独构建或重建它们,因为当一起构建时,Unity 编辑器会做出关于如何在每个 AssetBundle 中引用或嵌入内容的决策,这可能取决于其他 AssetBundle 中包含的内容。例外情况是,如果您是了解项目中 AssetBundle 之间引用和依赖关系的高级用户,在这种情况下,您有时可以只构建项目 AssetBundle 的子集。

AssetBundle 内部有什么?

由于您用于加载 AssetBundle 的 API 设计得很简单,因此它们隐藏了 AssetBundle 内部数据表示的细节。但是,了解结构可能很有用,尤其是在您使用工具提取或检查 AssetBundle 内容时。

AssetBundle 是一种容器文件格式,类似于 zip 文件。它具有二进制格式的标头并在其内部嵌入其他文件。这些其他文件包含两种类型

  • 序列化文件,其中包含序列化的 Unity 对象。这与 Player Build 中使用的二进制文件格式相同。对于包含资源的 AssetBundle,所有对象都写入单个序列化文件。对于包含场景的 AssetBundle,每个场景场景包含游戏环境和菜单。可以将每个唯一的场景文件视为一个唯一的关卡。在每个场景中,放置环境、障碍物和装饰,从本质上讲是分段设计和构建游戏。 更多信息
    参见 术语表
    都有两个序列化文件,一个包含场景层次结构中的对象,另一个包含任何引用的对象。
  • 资源文件,即为某些资源(纹理和音频)单独存储的二进制数据块。这种分离允许 Unity 使用多线程代码从磁盘高效地加载它们。

AssetBundle 文件始终包含一个序列化的 AssetBundle 对象。此对象充当 AssetBundle 内容的目录。这是您通过代码与之交互以从特定 AssetBundle 存档加载资源的对象,它还在使用 Addressables API 从 AssetBundle 加载资源时在内部使用。

向后兼容性

构建 AssetBundle 时,包含的对象使用您用于构建它的 Unity 编辑器版本的定义以及构建的项目中定义的 C# 类型进行序列化。每个类型的信息都记录在 AssetBundle 内部的名为“类型树”的结构中。这些类型信息在某种程度上会增加 AssetBundle 的大小,但对于在播放器版本与构建时的编辑器版本不匹配时启用加载这些对象至关重要。对于许多 Unity 功能,类型非常稳定,并且版本之间只会发生细微变化,因此向后兼容性支持效果很好。但是,在 Unity 功能发生重大变化的情况下,可能无法以在较新版本中获得预期结果的方式加载旧数据。在这种情况下,必须使用新版本的 Unity 重建 AssetBundle。

Unity 不支持向前兼容性,因此将使用新版本的 Unity 构建的 AssetBundle 加载到使用旧版本的 Unity 构建的播放器中可能会遇到加载内容的问题。

注意:默认情况下,用于构建文件的 Unity 编辑器版本包含在 AssetBundle 标头内。此信息在调查向后兼容性问题时很有用。但是,它也可能导致 AssetBundle 不必要地重建,并在进行编辑器的小幅升级后重建项目时导致不必要的客户端下载。为了避免这种情况,您可以排除编辑器版本,请参阅 BuildAssetBundleOptions.AssetBundleStripUnityVersion

对脚本对象的支持

AssetBundle 不包含程序集,也不用于分发新的 C# 类或对现有类的更改。相反,是 Player Build 包含已编译的程序集。这意味着要发布代码更改,必须重建和重新分发游戏或应用程序的主要构建。

但是,您可以使用 AssetBundle 分发已编译到 Player Build 中的类的实例的新对象,例如游戏的新项目。

例如,AssetBundle 可以包含 ScriptableObject 资源。当您从 AssetBundle 加载该资源时,Unity 会根据程序集名称、命名空间和类名找到匹配的类定义。它会创建一个该类的实例对象,并使用序列化值设置对象字段。

如果对象是基于类的旧定义序列化的,则 Unity 将使用其向后兼容性支持根据字段名称和其他记录在类型树中的信息匹配尽可能多的字段。

脚本通常使用 条件编译 指定特定于平台的代码。例如,使用像 UNITY_STANDALONE、UNITY_IOS 和 UNITY_ANDROID 这样的脚本符号。如果类或结构上的字段未在某些目标上编译,则 AssetBundle 内的对象序列化将不包含这些字段(并且它们也不会包含在类型树中)。这是 AssetBundle 必须为每个目标平台重建的另一个原因。

构建 AssetBundle 的方法

Unity 有两种支持的 API 用于构建 AssetBundle

  • 使用内置的原生 API,例如 BuildPipeline.BuildAssetBundlesAssetBundleUnityWebRequestAssetBundle。这是本手册部分中描述的功能。但是,此方法的级别较低,例如,它要求您了解资源依赖关系,自行确定包分配并编写自己的构建脚本。
  • 使用 Addressables 包。这是推荐的、更友好的选项,并且可以从 Addressables UI(用户界面) 允许用户与您的应用程序交互。Unity 目前支持三种 UI 系统。 更多信息
    参见 术语表
    直接定义和构建 AssetBundle。它使用相同的底层文件格式和相同的低级 Unity 加载和缓存服务,但通过更高级别、更抽象的 API 间接使用。因此,虽然本节中描述的许多概念适用于与 Addressables 一起使用的 AssetBundle,但您应该参考 Addressables 文档以获取实际使用信息。
通过文件夹将默认预设应用于资源
AssetBundle 工作流程