Version: Unity 6.0 (6000.0)
语言 : 中文
Use AssetBundles to load assets at runtime
Creating AssetBundles

AssetBundle

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

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

为任何独立平台构建的 AssetBundle 只能在该平台上加载。例如,在 iOS 上构建的 Bundle 与 Android 不兼容。其中一个原因是着色器、纹理和其他类型的数据基于 BuildTarget 内置到特定于平台的格式中。

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

AssetBundle 中有什么?

因为用来加载 AssetBundle 的 API 设计得很简单,并不考虑 AssetBundle 中数据的表示方式。但是,了解结构可能很有用,尤其是在使用工具提取或检查 AssetBundle 的内容时。

AssetBundle 是一种容器文件格式,类似于 zip 文件。它有一个二进制格式的头文件,并在其中嵌入了其他文件。这些附加的文件有两种类型:

  • 序列化文件,其中包含序列化的 Unity 对象。这与运行版本中使用的二进制文件格式相同。如果 AssetBundle 包含资源,则所有对象都将被写入单个序列化文件。对于包含场景的 AssetBundle,每个场景有两个序列化文件,一个包含场景层级视图中的对象,另一个包含所有引用的对象。
  • 资源文件,这是为某些资源(纹理和音频)单独存储的二进制数据块。这种分离方式允许 Unity 使用多线程代码从磁盘高效加载资源。

AssetBundle 文件始终包含一个序列化的 AssetBundle 对象。此对象的作用类似于 AssetBundle 内容的目录。这是通过代码进行交互的对象,用于从特定 AssetBundle 存档加载资源,使用 Addressables API 从 AssetBundle 加载资源时,也会在内部使用此对象。

强制向前兼容

在构建 AssetBundle 时,所含的对象会被序列化,此时将用到您在构建时所用的 Unity 编辑器版本的定义,以及在构建的项目中定义的 C# 类型。每种类型的信息都记录在 AssetBundle 中称为_类型树 (Type Tree)_ 的结构内。此类型信息在一定程度上影响 AssetBundle 的大小,不过,若在构建时播放器的版本与编辑器版本不匹配,启用加载这些对象将至关重要。对于许多 Unity 功能,类型相当稳定,并且仅在版本之间发生细微变化,因此向后兼容性支持运行良好。但是,在 Unity 功能发生重大变化的情况下,加载旧数据可能无法达到较新版本中的预期结果。在这种情况下,必须使用新版 Unity 重新构建 AssetBundle。

Unity 不支持向前兼容,因此,如果将使用新版 Unity 构建的 AssetBundle 加载到使用旧版 Unity 构建的播放器中,可能会在加载内容时出现问题。

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

支持脚本对象

AssetBundle 不包含程序集,也不用于分发新的 C# 类或更改现有类。它是包含已编译程序集的运行版本。这意味着要发布代码更改,必须重新构建并重新分发游戏或应用的主构建。

但是,您可以使用 AssetBundle 来分发新对象,这些对象将作为类实例编译到运行版本中,例如游戏的新项目。

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

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

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

AssetBundle 的构建方法

有两个受支持的 API 可用于为 Unity 构建 AssetBundle:

  • 使用内置的原生 API,例如 BuildPipeline.BuildAssetBundlesAssetBundleUnityWebRequestAssetBundle。本手册的本节中描述的就是此功能。但是,此方法的级别很低,例如,这需要您了解资源依赖关系,自行确定捆绑包分配,编写自己的构建脚本。
  • 使用 Addressables 包。这是推荐选项,更加易用,而且可直接从 Addressables__ UI__(即用户界面,User Interface)让用户能够与您的应用程序进行交互。Unity 目前支持三种 UI 系统。更多信息
    See in Glossary
    定义和构建 AssetBundle。它使用相同的底层文件格式和相同的低级别 Unity 加载和缓存服务,但通过更高级别、更抽象的 API 间接使用。因此,虽然本节介绍的许多概念适用于 Addressables 中使用的 AssetBundle,但您应该参阅 Addressables 文档,了解实际使用信息。
Use AssetBundles to load assets at runtime
Creating AssetBundles