Unity 5:使用 Asset Bundle 和 Asset Bundle Manager (3)

发表于2017-12-11
评论0 1.5k浏览

这篇是 Unity 官方教程 AssetBundles and the AssetBundle Manager 的翻译, 分三部分,这是第三部分。翻译不到之处请不吝指出。非常谢谢!

译者注:英文太啰嗦了,但是还是坚持的把它翻译完了。因为啰嗦的好处是起码能让概念多复习几遍,更容易记得住。如果读者觉得啰嗦,可以自行执行 跳读技能 来阅读译文。

本文的项目连接:http://u3d.as/jyk


示例 1:加载资源

  • 使用 “Asset/AssetBundles/Simulation Mode” 菜单打开模拟模式
  • 打开 “AssetBundleSample/Scenes/AssetLoader” 场景
  • 注意场景是个空的只有一个主摄像机,方向光和游戏对象 “Loader”
  • 进入 PlayMode
  • 然后会注意到一个 cube 已经从 AssetBundle 加载到场景里面了

这个场景是被 “LoadAssts.cs” 脚本驱动的。

在脚本编辑器里面打开脚本 “AssetBundleSample/Scripts/LoadAssets.cs”

脚本里有两个公共变量: public string assetBundleName; 和 public string assetName;

  • public string assetBundleName; 保存了要被加载的 AssetBundle 的名字
  • public string assetName; 保存了要已加载的 AssetBundle 中加载的资源的名字

这个脚本是由一个 Start() 函数和被 Start() 调用的两个协程组成的。Initialize() 调用了 DontDestoryOnLoad(), 设置了 AssetBundle 的路径和初始化了 AssetBundle 清单。在 InstantiateGameObjectAsync()中,如果资源不为空,AssetBundleManager.LoadAssetAsync() 调用资源和 AssetBundle 的名字。

重点注意下,在 “AssetBundleSample/Assets” 路径下查看 “MyCube” 资源,会发现 “MyCube” 依赖于 “MyMaterial”,而 “MyMaterial” 依赖于 “UnityLogo”。脚本中只有 “MyCube” 资源被调用,但是所有的依赖资源都被正确的加载了。

AssetBundle 的路径怎么设置也值得注意下。当场景在编辑器中或者从一个开发版 Build 中运行时,这段代码会给本地资源服务器设置 AssetBundle 的位置。(更多关于开发版 Build,请查看发布 Builds 文档。)模拟模式开启后,AssetBundle 会在编辑器中被模拟,这个设置将不会被使用。

对 DontDestoryOnLoad() 作用的理解。虽然在这个非常简单的脚本中并不是绝对需要它,但是他的存在是假设这个脚本会作为一个更复杂的项目的 AssetBundle 加载器基础,它需要在场景变化的以后依然存在。

示例 2:加载场景

  • 使用 “Asset/AssetBundles/Simulation Mode” 菜单打开模拟模式
  • 开始 “AssetBundleSample/Scenes/SceneLoader” 场景
  • 注意场景是个空的只有一个主摄像机,方向光和游戏对象 “Loader”
  • 开打 PlayMode
  • 然后会注意到一个 cube 和 plane 已经从 AssetBundle 加载到场景里面了

这个场景被 “LoadScene.cs” 脚本驱动着。

在脚本编辑其中打开 “AssetBundleSample/Scripts/LoadScenes.cs” 脚本。

脚本里有个两个公共变量:public string sceneAssetBundle; 和 public string sceneName;

  • sceneAssetBundle; 保持了要加载的 AssetBundle 的名字
  • sceneName; 保持了要从已加载的 AssetBundle 里加载的场景的名字

这个脚本是有一个 Start() 函数和被 Start() 调用的两个协程组成的。Initialize() 调用了 DontDestoryOnLoad(), 设置了 AssetBundle 的路径和初始化了 AssetBundle 清单。在 InitializeLevelAsync() 里使用 AssetBundleManager.LoadLevelAsync() 调用场景名字和 isAdditive 来请求一个场景。如果场景为空,AssetManager 会在控制台显示出错误,然后协程结束。

重点注意下,在 “AssetBundleSample/Assets” 路径下查看 “MyCube” 资源,会发现 “MyCube” 依赖于 “MyMaterial”,而 “MyMaterial” 依赖于 “UnityLogo”。只有 “TestScene” 场景被请求了。但在 “TestScene” 中的 “Cube” 和所有依赖的资源都被 AssetBundle Manager 正确的加载了。

AssetBundle 的路径怎么设置也值得注意下。当场景在编辑器中或者从一个开发版 Build 中运行时,这段代码会给本地资源服务器设置 AssetBundle 的位置。(更多关于开发版 Build,请查看 发布 Builds 文档。)模拟模式开启后,AssetBundle 会在编辑器中被模拟,这个设置将不会被使用。

对 DontDestoryOnLoad() 作用的理解。虽然在这个非常简单的脚本中并不是绝对需要它,但是他的存在是假设这个脚本会作为一个更复杂的项目的 AssetBundle 加载器基础,它需要在场景变化的以后依然存在。

示例 3:变体

要使用 AssetBundle 变体,需要编译 AssetBundle, 因为模拟模式下不支持它。在编译 AssetBundle 和它的变体钱,确保所有的资源以及被正确地指定 AssetBundle 名字和如果要被 AssetBundle 变体利用到的话,AssetBundle 变体的名字也要指定。

同时拥有 AssetBundle 名字和 AssetBundle 变体名字的资源

当所有的资源都指定到 AssetBundle 或者 AssetBundle 变体后,选择 “Assets/AssetBundles/Build AssetBundles” 菜单来编译它们。

Assets/AssetBundles/BuildAssetBundles

默认情况下,AssetBundle 会根据当前的平台优化,并编译进项目跟目录下的 “AssetBundles” 文件夹内,并按平台分组。

为了简化流程,不部署新编译出来的 AssetBundle 远程,需要开启本地资源服务器。通过 “Assets/AssetBundles/Local AssetBundle Server” 可以开启本地资源服务器。

启动本地资源服务器

本地资源服务器应该想其他任何网络连接一样受限制,可能是权限需求,防火墙和其他限制。本地资源服务器启动时会被设置到默认 IP 地址和端口的本地资源访问的服务器,通常是 http://192.168.1.115:7888/. 这个只是暂时的,它被存储在 AssetBundleManager/Resources/AssetBundleServerURL 文件里面。这些信息会被 AssetBundleManager 设置或自动改变,用户不需要关注它们。

包含当前 URL 和 端口的 AssetBundleServerURL

当本地资源服务器运行的时候,编译后 AssetBundle 可以被本地测试。

  • 选择 “Assets/AssetBundles/Simulation Mode” 确保模拟模式被禁用了
  • 选择 “Assets/AssetBundles/Local AssetBundle Server” 确保本地资源服务器开启
  • 打开 “AssetBundleSample/Scenes/VariantLoader”
  • 注意场景是个空的只有一个主摄像机,方向光和游戏对象 “Loader”
  • 退出 PlayMode (如果在 PlayMode 下)
  • 打开 PlayMode
  • 选择 “Load HD”
  • 注意同一个 Cube 和 Sprite 加载进场景了,但是材质和他依赖的独立纹理和 Sprite 纹理却从不同的 AssetBundle 加载。这些材质有不同的颜色,图片有更高的分辨率。

这个场景是被 “LoadVariant.cs” 脚本驱动的。

从编辑器中打开 “AssetBundleSample/Scripts/LoadVariants”。

这个脚本跟 “LoadScenes.cs” 几乎差不多。主要的区别就是用来区别需要加载的 AssetBundle 变体的变量和设置当前变体的代码。还有用来创建 UI 按钮的额外的代码。

  • public string variantSceneAssetBundle; 保存要加载的 AssetBundle 的名字
  • public string variantSceneName; 保存要从已加载的 AssetBundle 中加载的场景名字
  • private string[] activeVariants; 保存用来区分需要加载的 AssetBundle 变体的 AsssetBundleVariantNames
  • private bool bundlesLoaded 用来在加载完资源之后隐藏 UI

脚本由一个 BeginExample() 函数和被 Start() 调用的两个协程组成。 BeginExample() 在 OnGUI()函数中 被 Load HD 或者 Load SD 按钮调用。Initialize() 调用了 DontDestoryOnLoad(), 设置了 AssetBundle 的路径和初始化了 AssetBundle 清单。在 BeginExample() 方法里,在调用 Initialize() 和 InitializeLevelAsync() 之间,当前的变体被设置了。这里被设置的值从靠 OnGUI 里的 “Load HD” 或者 “Load SD” 按钮创建的。在 InitializeLevelAsync() 里使用 AssetBundleManager.LoadLevelAsync() 调用场景名字和 isAdditive 来请求一个场景。如果场景为空,AssetManager 会在控制台显式出错误,然后协程结束。

这里需要重视的是 AssetBundle 变体是怎么样加载的。activeVariants 数组包含了所有可能的 “激活的” 变量名列表。这个数组用来设置 AssetBundleManager.ActiveVariants 属性。当加载一个含有变体的 AssetBundle 时,AssetBundle Manager 将会选择在 ActiveVariants 属性里含有 “激活” 的变体名字的 AssetBundle。当前的示例中,ActiveVariants 属性只包含一个元素。当前的变体要么是 “sd”,要么是 “hd”。在 ActiveVariants 属性中有多个实体是有可能的。比如,可能有下面一些 AssetBundle: my-material.sd,my-material.hd, my-text.english,my-text.catalan,my-text.welsh。ActiveVariants 属性可以包含 “hd” 和 “danish” 两者或者 “sd” 和 “english” 等等任何可以有其他可能组合的变体名。这种方式下,AssetBundle Manager 分开可以加载 hd/sd 图片和语言选择。

有些规则值得注意下。如果,因为一些因素,有一些指定了变体的 AssetBundle,但是在 ActiveVariants 属性里没有 “激活” 的变体名 - 比如当前例子中的 “sd” 或者 “hd” 不在 ActiveVraiants 属性中 - AssetBundle Manager 将会简单的选择第一个它发现的正确名字的 AssetBundle 而忽略变体名。再如果,又因为一些因素,在 ActiveVariants 属性里对同一个 AssetBundle 集合有多个 “激活” 的变体名 - 比如, 在当前的例子里,“sd” 和 “hd” 都在ActiveVariants 属性里 - AssetBundle Manager 将选择在 ActiveVariants 属性中的第一个变体名。

示例 4:坦克示例

这个更复杂的示例将包括这篇文章中的所有内容,包括从 AssetBundle 中加载场景和为分辨率,内容和位置加载 AssetBundle 变体。

  • 选择 “Assets/AssetBundles/Simulation Mode” 确保模拟模式被禁用了
  • 选择 “Assets/AssetBundles/Local AssetBundle Server” 确保本地资源服务器开启
  • 打开 “AssetBundleSample/Scenes/TanksLoader”
  • 注意场景是个空的只有一个主摄像机,方向光和游戏对象 “Loader”
  • 进入 PlayMode
  • 选择一个分辨率,风格和语言
  • 注意在 UI 里的选择项就是加载的资源
  • 如果没有显式的选择一个,AssetBundleManager 将自动选择(基于上面的原则)一个并且在命令行输出一个警告。

场景靠 “LoadTanks.cs” 脚本驱动。

在编辑器里面打开 “AssetBundleSample/Scripts/LoadTanks.cs” 脚本。

这个脚本与 “LoadScenes.cs” 和 “LoadAssets.cs” 非常像。脚本使用代码去加载依赖变体的场景和一样依赖变体的额外的游戏对象。也有一些额外的代码创建 UI 按钮。

  • public string sceneAssetBundle; 保存携带场景的 AssetBundle 的名字
  • public string sceneName; 保存要从已加载的 AssetBundle 中加载的场景名字。
  • public string textAssetBundle; 保存携带文字资源的 AssetBundle 的名字
  • public string textAssetName; 保存要从已加载的 AssetBundle 中加载的文字资源的名字
  • private string activeVariants; 保存要传给 AssetBundleManager 的 ActiveVariants
  • private bool bundlesLoaded; 用来资源加载之后隐藏 UI
  • private bool sd, hd, normal, desert, englisth, danish; 保存用来设置 ActiveVariants 的值
  • private string tankAlbedoStyle, tankAlbedoResolution, languge; 保存用来设置 ActiveVariants 的值

脚本由一个 BeginExample() 函数和被 Start() 调用的两个协程组成。 BeginExample() 在 OnGUI()函数中 被 “Load Scene” 按钮调用。Initialize() 调用了 DontDestoryOnLoad(), 设置了 AssetBundle 的路径和初始化了 AssetBundle 清单。在 BeginExample() 方法里,在调用 Initialize() 和 InitializeLevelAsync()之间,当前的变体被设置了。这里被设置的值从靠 OnGUI 里的 “Load Scene” 按钮创建的。在 InitializeLevelAsync() 里使用 AssetBundleManager.LoadLevelAsync() 调用场景名字和 isAdditive 来请求一个场景。如果场景为空,AssetManager 会在控制台显式出错误,然后协程结束。在 InstantiateGameObjectAsync() 中资源和 AssetBundle 名字被 AssetBundleManager.LoadAssetAsync() 调用。如果调用的资源不为空,它会被实例化。如果 AssetBundle 不能被加载或者资源不能被请求,控制台会打印出错误来。

这小结要注意的内容是,多个 资源,AssetBunle 和 AssetBunle 变体怎么被访问和加载进场景里,和怎么样在运行期设置这些值。

Unity 5: 使用Asset Bundle 和 Asset Bundle Manager (1)

Unity 5:使用 Asset Bundle 和 Asset Bundle Manager (2)

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