「翻译」Unity中的AssetBundle详解(五)

AssetBundle 管理器

AssetBundle Manager 可以在这里下载,是由 Unity 制作的一种工具,可以使 AssetBundles 更加精简。下载和导入 AssetBundle Manager 软件包不仅添加了一个新的API调用来加载和使用AssetBundles,而且还添加了一些编辑器功能来简化工作流。此功能可以在“资产”菜单选项下找到。此新部分将包含以下选项:

模拟模式

启用模拟模式允许 AssetBundle Manager 使用 AssetBundles,但不需要实际构建捆绑包。编辑器会看到 Assets 已分配给 AssetBundles,并直接使用 Assets ,而不是实际上从 AssetBundle 中提取 Assets。
使用模拟模式的主要优点是 Assets 可以被修改、更新、添加和删除,而不需要每次重新构建和部署AssetBundles。值得注意的是,AssetBundle 变体不适用于模拟模式。如果你需要使用变体,则你需要使用本地 AssetBundle 服务器。

本地 AssetBundle 服务器

AssetBundle Manager 还可以启动一个本地 AssetBundle 服务器,该服务器可用于在编辑器或本地构建(包括移动端)中测试 AssetBundles。获取本地 AssetBundle 服务器工作的规定是必须在项目的根目录中创建一个名为AssetBundles的文件夹,该文件夹与 Assets 文件夹的级别相同。如下图:

创建文件夹后,你需要将 AssetBundles 构建到此文件夹。为此,请从新菜单选项中选择Build AssetBundles。这将为你构建它们到该目录。现在你已经建立了 AssetBundles(或已经决定使用模拟模式),并准备开始加载 AssetBundles。我们来看看 AssetBundle Manager 对我们提供的新的API调用。

AssetBundleManager.Initialize()

此函数加载 AssetBundleManifest 对象。在使用 AssetBundle Manager 开始加载资产之前,你需要调用它。在一个非常简单的例子中,初始化 AssetBundle Manager 可能如下所示:

1
2
3
4
5
6
7
8
9
10
IEnumerator Start()
{
yield return StartCoroutine(Initialize());
}
IEnumerator Initialize()
{
var request = AssetBundleManager.Initialize();
if (request != null)
yield return StartCoroutine(request);
}

AssetBundle Manager 使用你在 Initialize() 期间加载的清单来帮助幕后的许多功能,包括依赖关系管理。

Loading Assets

你正在使用 AssetBundle Manager,你已初始化它,现在你可以加载某些资产。我们来看看如何加载 AssetBundle 并从该 Bundle 中实例化一个对象:

1
2
3
4
5
6
7
8
9
10
11
12
IEnumerator InstantiateGameObjectAsync (string assetBundleName, string assetName)
{
// Load asset from assetBundle.
AssetBundleLoadAssetOperation request = AssetBundleManager.LoadAssetAsync(assetBundleName, assetName, typeof(GameObject));
if (request == null)
yield break;
yield return StartCoroutine(request);
// Get the asset.
GameObject prefab = request.GetAsset<GameObject> ();
if (prefab != null)
GameObject.Instantiate(prefab);
}

AssetBundle Manager 会异步执行所有的加载操作,因此它返回一个加载操作请求,它在调用 yield return StartCoroutine(request)时加载 Bundle;接着我们需要做的是调用GetAsset<T>() 从 AssetBundle 加载游戏对象。

Loading Scenes

如果你有一个 AssetBundle 名称分配给场景,并且你需要加载该场景,则需要遵循稍微不同的代码路径。模式是相同的,但有微小的差异。以下是从AssetBundle加载场景的方法:

1
2
3
4
5
6
7
8
IEnumerator InitializeLevelAsync (string levelName, bool isAdditive)
{
// Load level from assetBundle.
AssetBundleLoadOperation request = AssetBundleManager.LoadLevelAsync(sceneAssetBundle, levelName, isAdditive);
if (request == null)
yield break;
yield return StartCoroutine(request);
}

正如你所看到的,加载场景也是一个异步的,LoadLevelAsync返回一个加载操作请求,需要传递给一个StartCoroutine 才能加载场景。

Load Variants

使用 AssetBundle Manager 加载变量实际上并不会改变在场景或资产中加载的代码。所有需要完成的操作都是设置 AssetBundleManager 的 ActiveVariants 属性。ActiveVariants 属性是一个字符串数组。只需构建一个字符串数组,其中包含在将它们分配给资产时创建的变体名称。以下是如何使用 hd 变体加载场景 AssetBundle。

1
2
3
4
5
6
7
8
9
10
IEnumerator InitializeLevelAsync (string levelName, bool isAdditive, string[] variants)
{
//Set the activeVariants.
AssetBundleManager.ActiveVariants = variants;
// Load level from assetBundle.
AssetBundleLoadOperation request = AssetBundleManager.LoadLevelAsync(variantSceneAssetBundle, levelName, isAdditive);
if (request == null)
yield break;
yield return StartCoroutine(request);
}

在代码中的其他地方构建的字符串数组(可能是从按钮点击或其他一些情况)中传递的地方。如果可用,则将加载与设置的活动变体相匹配的 Bundles。

使用 AssetBundles 进行修补

修补 AssetBundles 与下载新的 AssetBundle 并替换已存在的 AssetBundle 一样简单。如果使用WWW.LoadFromCacheOrDownloadUnityWebRequest 来管理应用程序的缓存AssetBundles,则将不同的版本参数传递到所选的 API 将触发下载新的 AssetBundles。补丁系统中更难解决的问题是检测哪个 AssetBundles 需要被替换。补丁系统需要两个信息列表:

  • 当前下载的 AssetBundles 的列表及其版本信息
  • 服务器上的 AssetBundles 列表及其版本信息

修补程序应该下载服务器端 AssetBundles 的列表,并比较 AssetBundle 列表。应该重新下载缺少 AssetBundles 或版本信息已更改的 AssetBundles。还可以编写一个自定义系统来检测对 AssetBundles 的更改。编写自己系统的大多数开发人员都选择使用行业标准的数据格式来存储 AssetBundle 文件列表,例如JSON,以及用一个标准 C# 类来计算校验和,如MD5。Unity 使用确定性方式排序的数据构建 AssetBundles。这允许具有自定义下载器的应用程序实现差分补丁(differential patching)。
Unity 不提供用于差分修补的任何内置机制,当使用内置缓存系统时,WWW.LoadFromCacheOrDownloadUnityWebRequest 都不会执行差异修补。如果需要进行差分修补,则必须写入自定义下载器。

原文链接:

  1. AssetBundle Manager
  2. Patching with AssetBundles

同系列文章

同系列文章

「翻译」Unity中的AssetBundle详解(一)

「翻译」Unity中的AssetBundle详解(二)

「翻译」Unity中的AssetBundle详解(三)

「翻译」Unity中的AssetBundle详解(四)

「翻译」Unity中的AssetBundle详解(五)