这篇是 Unity 官方教程 AssetBundles and the AssetBundle Manager 的翻译, 分三部分,这是第一部分。翻译不到之处请不吝指出。非常谢谢!
介绍
AssetBundle 允许按需地从本地或者远程服务器上加载资源(Asset)。通过 AssetBundle 的方式,资源可以远程存储,有需要的时候访问,这样提升了项目的灵活性和降低初始程序的大小。
这篇教程将会介绍 AssetBundle 和及其应用,AssetBundle 流程的步骤和各阶段和怎么样编译和测试 AssetBundle 及其变体 - 所有的一切可以用 AssetBundle Manager 来简化创建,测试和部署 AssetBundle。教程的最后一部分将使用一些加载和使用 AssetBundle 变体的简单用例和脚本示例。
演示项目
在开始教程之前,最后先下载好 AssetBundle 和 AssetBundle Manager 的示例程序。
什么是 AssetBundle
AssetBundle 是由 Unity 编辑器在编辑时期创建的,可以被编译出来的程序在运行期使用的文件。AssetBundle 可以包含模型,材质,纹理和场景文件等资源。但是 AssetBundle 不能包含脚本。
明确一点说,一个 AssetBundle 就是存储项目资源和 / 或场景集合的文件,目的是为了之后在游戏或者程序中加载。
AssetBundle 可以被在 Unity 中编译出来的游戏或者程序按需加载。它允许传送和异步加载像模型,材质,声音剪辑,
甚至是整个场景。当在程序中初次运行时, AssetBundle 会被存储到本地 “预缓存” 以备以后被立即加载。Assetbundle 的主要目是为了需要的时候能从远程传送内容并加载进程序。AssetBundle 可以包含可以被 Unity 识别的任何资源类型,包括二进制文件。唯一的另外就是不允许是脚本资源。
AssetsBundle 有很多用处。比如新的内容可以动态地在程序中加载和释放。可以很简单实现发布后的可下载内容(DLC, Downloadable Content)。
程序第一次安装的的时候的大小或者磁盘占用空间会减少,资源只有安装的程序需要的时候才会被加载。平台或者设备相关的资源加载时可以不必要下载或冗余存储其他平台和方案中的资源。本地化的程序可以更容易来下载和安装基于用户位置,语言和偏好的资源。新的内容可以下修复,改变或更新,而不需要重新发布程序。
AssetBundle 内项目资源的组织严重依赖于项目的需求。但是,也有一些可以更好的理解 AssetBundle 的原则。
- AssetBundle 是整体被下载和缓存的
- AssetBundle 不需要整体被加载
- AssetBundle 中的资源可以包括依赖的其他资源
- AssetBundle 中的资源可以共享依赖的其他资源
- 每个 AssetBundle 在文件大小和处理上都有一些技术上的开销。
- 每个平台上的 AssetBundle 都需要单独编译
AssetBundle 是整体被下载的。如果在一个 AssetBundle 中包含不需要立即加载,甚至不需要加载进场景的资源,它们也会占用下载带宽和存储空间。
AssetBundle 的内容不需要整体加载的。一旦 AssetBundle 被下载过了,资源可以有选择性的从 AssetBundle 中加载。
资源能包括依赖的其他资源。比如,一个模型有好几个依赖。最终在游戏里的摩西不光只有网格数据,它会是一个包含所有组件和组件的依赖项的游戏对象(GameObject)。
应用了材质的模型
这个模型依赖于在模型的 Mesh Renderer 组件中的一个材质资源,而这个材质资源依赖于应用在材质的 Albedo 纹理上的纹理资源。实际上,这个坦克依赖了三个材质,而不是仅仅一个。
坦克模型资源的依赖链:模型 > 材质 > 纹理
资源可以共享依赖的其他资源。比如,两个模型可以共享同一个材质, 相应的可能依赖于同一个纹理。
两个共享同一个材质的不同的岩石柱模型
每个 AssetBundle 都会有一些技术上的开销。AssetBundles 是包装资源的文件。这个包装会增加 AssetBundle 的总大小。即使这个增量不大,可测量。AssetBundle 还要求一定量的处理来组织,创建,上传和维护。从技术上和处理上,使用的 AssetBundle 越多,其在项目中的开销越大。
当组织 AssetBundle 时,需要在 使用数量多体积小但需要跟踪和生成开销的 AssetBundle 还是
数量小但体积大且包含很多不必要的多余的数据的 AssetBundle 中做出平衡。具体的平衡策略严重依赖于项目的需求。
AssetBundle 的内容是根据当前的 Import Settings 和 平台来编译和优化的。所以,AssetBundle 需要为不同平台编译。
清单和依赖管理
理解关于依赖和依赖管理,有几个重要的点。
资源依赖永远不会丢失。当 AssetBundle 编译的时候,即便独立的资源没有指定到任何的 AssetBundle,也会跟着被选中的资源中被自动的加入 AssetBundle中。这样很便捷并且可以防止独立资源的丢失。尽管如此,这还是会引起资源的重复。比如,以上面使用同一个材质的两个岩石柱为例,如果两个岩石柱分开在不同的两个 AssetBundles 中并且这个材质没有显式的指定到一个 AssetBundle 上,这个材质就会被加入到这两个包含岩石柱的 AssetBndles 中。这个值得注意,两个重复的资源现在被存储到各自的 AssetBundle 中,资源的依赖性被分离了。每个模型资源现在依赖于各自的材质资源的本地拷贝,丢失了共享材质的优势。为了比避免这个发生,这个材质需要显式的指定到一个 AssetBundle 中。这样 AssetBundle 可以自己使用它也,也可以和其他资源一起共享。这种情况下,拥有岩石柱的 AssetBundles 依赖于拥有岩石材质的 AssetBundle 了。
项目的 AssetBundle 的依赖和其他信息存储在 清单(Manifest) 中。清单非常像关于项目的 AssetBundles 的 “目录”。当 AssetBundle 在编译的时候,Unity 会生产大量的数据。数据的细节存储在清单里。每个平台都会创建一个清单。清单为编译对象列举了所有从项目创建的 AssetBundles,存储位置和跟踪他们的依赖。利用清单,可以查询所有的 AssetBundles 和他们的依赖。
对于 AssetBundles 有一种特殊设置,叫做 AssetBundle 变体。AssetBundle 变体被设计来支持更特殊的使用场景 - 对单独的对象映射不同的资源选择。这对于需要依据一些标准,如分辨率,语言,地区或者用户偏好来从很多可能中选择一个资源的项目特别有用。AssetBundle 变体可以包含用来覆盖所有支持的选项的多种资源,
并且按需从选择的 AssetBundle 变体中映射期望的资源到对象上。
AesstBundles 是包含模型,材质,纹理和场景文件等资源文件的文件。AssetBundles 在编辑器的编辑期创建,可以被编译出来的程序之后使用。AssetBundles 被设计来从本地或远程源中按需加载资源。AssetBundles 可以拥有变体,可以基于用户偏好映射到对象上。
关于使用 AssetBundle 和 AssetBundle Manger 的更多细节,请看这系列的下一个教程。