AssetBundle 和 AssetBundle Manager 使用实践

发表于2016-02-22
评论1 5.7k浏览
  AssetBundles 允许从本地或者服务器按需指定和加载资源(Assets)。通过 AssetBundles 技术,资源可以存放在远端的服务器上,当游戏中需要使用它们时,再去按照需要去加载这些资源。这种技术增加了项目的灵活性,并且减少了应用程序的初始包的体积大小。
  本文将介绍 AssetBundles 技术,并且讨论如何去使用它,AssetBundles 工作流的步骤和阶段,如何将资源打包到 AssetBundle 中去,如何使用以及何时应该使用 AssetBundle Variants,如何构建和测试 AssetBundles 和 Variants。所有的这些,我们都可以使用 AssetBundle Manager 来简化AssetBundles 的创建、测试和发布环节。本文的最后我们将介绍一个使用 AssetBundles 和 Variants 的实际例子。


一、示例项目
  示例项目下载下来。AssetBundles 允许从本地或者服务器按需指定和加载资源(Assets)。通过 AssetBundles 技术,资源可以存放在远端的服务器上,当游戏中需要使用它们时,再去按照需要去加载这些资源。这种技术增加了项目的灵活性,并且减少了应用程序的初始包的体积大小。AssetBundle 是什么
  AssetBundles 是有 Unity 编辑器在编辑环境中创建的一些列的文件,这些文件可以被用在项目的运行环境中。 AssetBundles 可以包括的资源文件有模型文件(models)、材质(materials)、纹理(textures)和场景(scenes)。AssetBundles 不能包含脚本文件。
  具体来说,一个 AssetBundle 就是把一系列的资源文件或者场景文件以某种方式紧密保存的一个文件。这个 AssetBundle 文件可以被单独加载到可执行的应用程序中。AssetBundles 可以由被 Unity 构建的游戏或者应用按需加载使用。这允许对像模型、纹理、音频、甚至是整个的游戏场景这样的资源进行流式加载和异步加载。AssetBundles 可以预缓存(pre-cached)和存储在本地,这样在运行时就可以立即加载它们。但是 AssetBundles 技术的主要的目的是在需要的时候能够从远端的服务器上按需请求特定的资源,并加载到游戏中。AssetBundles 可以包含 Unity 可以识别的任何类型的资源,包括自定义的二进制数据。唯一的例外是,脚本资源是不被允许的。
  有很多 AssetBundles 的使用案例。新的内容可以被动态的从应用程序中加载或者卸载。Post-release DLC 可以被更容易的实现。一个应用程序的磁盘占用或大小可以再第一次发布时被减小,在程序被安装后,在按照需要加载必要的资源。平台和设备相关的资源可以被正确的加载,而不需下载和存储当前设备不需要的平台或者分辨率所对应的资源文件。国际化也变得很容易,只需要根据用户的地理位置、语言和偏好设置来下载需要的资源就可以了。应用程序可以不需要提交新的版本就可以做到用新的资源内容来修复、改变和更新。
  应该怎样把一个项目的资源具体组成成 AssetBundles,这将严重依赖于具体项目的需求。但是下面这些基本的原则可以帮助我们更好的理解 AssetBundles。
· AssetBundles 是需要整体下载和缓存的。
· AssetBundles 不需要整体的加载到应用程序中,可以只加载其中的某些资源。
· 在 AssetBundles 中的资源对其他资源有依赖关系。
· 在 AssetBundles 中的资源可以同其他资源具有相同的依赖关系。
· 每个 AssetBundle 都有一些技术开销,即在文件的大小上,也在管理这些文件上。
· AssetBundles 应该为每个目标平台单独构建。
  每一个 AssetBundle 都是被整体下载的。如果一个 AssetBundle 包含了一些不是被立即使用的资源,甚至它们都不会被加载到当前这个场景中,它们也会耗费下载时的带宽和存储时的磁盘空间。
AssetBundles 的内容不需要被全部加载到应用程序中。只要 AssetBundle 被下载下来了,不同的资源就可以按照需要选择性的被加载。
  一些资源可能会对其他资源有依赖关系。比如,一个模型资源可以有几个依赖。一个游戏中的模型不只是有网格数据(mesh data),实际上它是一个拥有它所有 Components 的 GameObject,以及每个 Component 自己做依赖的依赖关系。


一个网格模型及其所使用的材质

  这个模型在 Mesh Renderer 中依赖于一个材质资源,而一个材质资源的 Albedo Texture 属性又依赖于一个纹理资源。所以,实际上这个坦克的模型依赖于三个资源,而不只是一个。


这个坦克模型的资源依赖链:模型 > 材质 >纹理

  资源可以共享资源,例如,两个不同的模型可以共享相同的材质球,进而可以依赖一个纹理。
每个AssetBundle有一些技术开销。 AssetBundles是文件包的资产。 这个包装器增加了AssetBundle的总体规模。 尽管这不是一个显著增加的大小,它是可以衡量的。 AssetBundles还需要一定的管理组织,创建、上传和维护。 越多的AssetBundles使用增加开销的项目,技术和管理。
  在组织AssetBundles的结构时,到底怎么去平衡,是把AssetBundles分成很多小的但是会耗性能的, 还是弄成几个大的但是囊括一些不必要的东西,这个需要根据你项目的实际情况而权衡。  
AssestBundle的目录被以优化的方式编译到目标平台上根据目标平台的导出设置,因为这样所以AssestBundles需要导出到各个目标平台。

二、依赖关系和依赖管理
有几个要点理解关于依赖和依赖关系管理。
  Assest资源的依赖关系从来没有丢失过,如果这个依赖的assestAssestBundle被创建时没有指定任何的AssestBundle依赖的Assest连同选中的Assest将被添加到AssestBundle这是非常方便和避免依赖Assest的损失。然而,这也会导致Assest重复。例如,使用两个岩石上面共享相同的Material,如果岩石列在单独的AssetBundles和Material没有显式地指定一个AssetBundle,将被添加到包含那种Material的两个 AssetBundles包中。值得注意的事,当这么做的时候,两个重复的资源将被存储在各自的AssetBundles而且依赖关系也破裂了,每个模型的Assest将依赖自己复制出来的Material,没有了共享Assest的任何优势。为了防止这种情况的发生,这些材料需要显式地指定一个AssetBundle,这可以实现对自己和其他资源的分享。用这种方法,这两个岩石的AssestBundle将依赖这个岩石Material。
  这些依赖关系和关于项目中AssetBundles的信息存储在一个清单中,清单很像一个目录,当AssestBundle被创建时,unity统一生成大量数据,这些数据保存清单的细节,每一个目标平台有一个对应的清单,清单列出所有为当前平台所需要的AssetBundles存储,跟踪和依赖项。 使用清单,可以查询所有AssetBundles和它们的依赖项。
  有一个关于AssetBundles的特别的设置被叫做 AssetBundle Variants,AssetBundle Variants目的在于一种特殊的情况:在项目中重新映射一个不同Assest中的单个对象,这对于一个需要基于标准分辨率、语言、定位、或用户偏好选择不同的Assest特别有用。 AssetBundle Variants可以容纳所需的各种Asset的覆盖所有支持选择对象和所需的Asset可以根据需要被映射到该对象的选择的AssetBundle Variants
  AssetBundles文件包含资产文件,如模型、材料、材质和场景。AssetBundles在辑器编辑创建在游戏中使用,AssetBundles旨在从本地或远程加载资源。AssetBundles可以变异映射到对象根据现场用户的偏好。

三、Working with AssetBundles and the AssetBundle Manager
  对于使用AssetBundles的一个关键和重要的工作是对Asset构建测试,通常,AssetBundles会定期的发生改变,所以需要定期的创建AssetBundles,然后将其上传到一个远程主机并通过一个网络连接的工作项目测试这些托管AssetBundles。
  这个关于AssetBundle Manager处理AssetBundles的一些小细节,AssetBundle Manager提供了一个高级的API大大提高了工作流。

四、使用AssestBundles
AssetBundles工作步骤编辑大致分为以下步骤: 
· 在编辑器中建立AssetBundles。
· 上传AssetBundles外部存储器。
· 在运行时下载AssetBundles。
  值得注意的是,一些AssetBundles可以存储在本地,以保证立即默认加载,这有助于防止一个应用程序的安装不能从远程下载所需AssetBundles。例如,当应用程序没有访问下载内容时应用程序将从本地AssetBundles加载默认语言和本地化数据。
  同时也值得注意的是,一个AssetBundles会根据平台进行打包, AssetBundle根据导入的设置和目标平台中设置构建为目标平台进行编译和优化。
  在下面这个简单的场景中,一种方式就是打包包括地面,沙丘,岩石,树,仙人掌。这个场景允许包括所有从属的材质,因为这一切都简单的不行,也不会因为分辨率的改变而改变,坦克模型会有自己的AssetBundle,这将允许更改或更新玩家信息。想要完成这个坦克的GameObject创建,需要额外依赖两个AssetBundle一个是材质球,一个是纹理,这么做对于更新这个材质球和纹理来说,将会造成最小的麻烦,也允许选择版本或者多个版本,从多个版本中选择一个需要的AssetBundle来实现平台,国际化或者目标设备的区分。


在编辑器中组织和设置AssetBundle,资源必须被分配给一个AssetBundle,当查看一个资源时,你可以Inspector窗口的最下面找到assestbundle的名字和其他assestbundle  Variant,预览窗口打开才能看到他们。


使用AssetBundle名称下拉菜单进行分配资源,在这里要不选择一个现有的要不创建一个新的.


  选择一个新的字符串创建一个新的AssestBundle,将没有被赋值的资源从AssestBundle中删除掉。如果想从列表中删除一个AssestBundle名字,那必须要把所有的分配给这个AssestBundle的资源的名字都从AssestBundle中删除掉。然后可以选择Remove Unused Names,将删除所有没被使用的AssestBundle的名字。
  资源将被分配到被选中的AssestBundle中,严格的说AssestBundle的名字应该小写,如果不遵循  那unity会自动做些调整。

五、使用AssetBundle Variants
  允许以各种不同的解决方案解决加载问题,包括下载、存储和更新,一种特定的情况就是AssetBundle 可以依据设备来加载不同的用户偏好等,这是利用AssetBundle Variants。场景中的一个物体上同一个资源AssetBundle Variants提供不同的Variants,AssetBundle Variants可以实现替换不同的资源到同一个物体上,只有一种Variants可以在任何时间进行加载。
  AssetBundle Variants在很多情况上多可以使用,AssetBundle Variants可以为不同分辨率的机器或者高低显卡配置不同的机器或者不同面数的多边形提供相同的资源,AssetBundle Variants可以根据文本、图像、纹理和字体可以为每个受支持的语言不同,地区或主题创建不同的对象。这些资源保存了一系列信息。

这是一个AssetBundle 小例子




  在上面的例子中,两个文件夹中的MyAssets-HD和MyAssets-SD已经分配给名叫myassets的AssetBundle,然后得到一个是别名分别是hd和sd,注意现在这两个资源具有相同的名称和层次结构,在创建一个资源的时候父目录被指到一个AssestBundle上,没有被直到任何一个AssestBundle的子物体也会被分配到这个父物体的AssestBundle上。指的注意的是,可以根据AssestBundle的名称创建一个一个层次菜单目录。

注意下面图片的AssestBundle有一个路径variant/ myassets 


  这将为名叫myassets的AssestBundle创建一个父菜单,叫variant。一旦一个资源被分配好了之后需要被打包和测试。

六、使用AssetBundle Manager
  unity有一个低级的API可以与AssetBundles工作,但这没有介绍,可以自己看API.在这个教程中主要集中介绍AssetBundle Manager和一些高级的API。AssetBundle Manager是一个可以下载下来的包,可以安装在任何现有的工程中,将提供一个高级的API改进工作流程。在项目中使用AssetBundle Manager,只需将它添加到项目的资产文件夹。

如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引