AssetBundle工作流程
将资产分配给AssetBundles
要将给定资产分配给AssetBundle,请按照下列步骤操作:
- 从项目视图中选择要分配给捆绑包的资产
- 检查检查器中的对象
- 在检查器的底部,您应该看到一个分配AssetBundles和Variants的部分:
- 左侧下拉分配AssetBundle,而右侧下拉分配变量
- 单击左侧下拉列表,显示“无”,以显示当前已注册的AssetBundle名称
- 单击“新建…”以创建新的AssetBundle
- 输入所需的AssetBundle名称。请注意,AssetBundle名称确实支持一种文件夹结构,具体取决于您键入的内容。要添加子文件夹,请用“/”分隔文件夹名称。例如:AssetBundle名称“environment / forest”将在环境子文件夹下创建名为forest的包
- 一旦选择或创建了AssetBundle名称,您可以重复此过程以右手下拉以分配或创建变体名称(如果需要),构建AssetBundle不需要变体名称。
添加打包工具栏
using UnityEditor;
using System.IO;
public class CreateAssetBundles
{
[MenuItem("Assets/Build AssetBundles")]
static void BuildAllAssetBundles()
{
string assetBundleDirectory = "Assets/AssetBundles";
if(!Directory.Exists(assetBundleDirectory))
{
Directory.CreateDirectory(assetBundleDirectory);
}
BuildPipeline.BuildAssetBundles(assetBundleDirectory, BuildAssetBundleOptions.None, BuildTarget.StandaloneWindows);
}
}
这样就会有一个打包工具,如果不是WIN平台,自行更改BuildTarget。
那如何加载
打算从本地存储加载:
public class LoadFromFileExample extends MonoBehaviour {
function Start() {
var myLoadedAssetBundle = AssetBundle.LoadFromFile(Path.Combine(Application.streamingAssetsPath, "myassetBundle"));
if (myLoadedAssetBundle == null) {
Debug.Log("Failed to load AssetBundle!");
return;
}
var prefab = myLoadedAssetBundle.LoadAsset<GameObject>("MyObject");
Instantiate(prefab);
}
}
自己托管AssetBundles并需要将它们下载到游戏中
IEnumerator InstantiateObject()
{
string url = "file:///" + Application.dataPath + "/AssetBundles/" + assetBundleName;
UnityEngine.__Networking__.UnityWebRequest request = UnityEngine.__Networking__.UnityWebRequest.GetAssetBundle(url, 0);
yield return request.Send();
AssetBundle bundle = DownloadHandlerAssetBundle.GetContent(request);
GameObject cube = bundle.LoadAsset<GameObject>("Cube");
GameObject sprite = bundle.LoadAsset<GameObject>("Sprite");
Instantiate(cube);
Instantiate(sprite);
}
GetAssetBundle(string, int)获取AssetBundle的位置的URL以及要下载的包的版本。
在此示例中,我们仍然指向本地文件,但string url可以指向您拥有AssetBundles的任何URL。
UnityWebRequest有一个特定的句柄来处理AssetBundles
DownloadHandlerAssetBundle,它从请求中获取AssetBundle。
分配策略
三种大的分配策略:
-
逻辑实体分组:
根据资源所代表的项目功能部分分配,比如资源属于用户界面,角色,环境等,这样来分配。
意思就是在根据游戏中的逻辑上的实体来分配,比如属于角色的所有东西都打在角色的包里面
逻辑实体分组特别适用于可下载内容(DLC),比如这个DLC只是更改了一些场景景物,那么我们只需要更改我们的场景模型包,而玩家也只需要下载这个更改后的包。
但是我的想法是另外一种:
比如在场景修改某个物体或者添加了一些新的下载内容后,我们只需要将这些修改后的或者新的内容打入新的AB包就可以只下载新的AB包。在玩家拥有DLC时,加载新的AB包就可以了。如果没有DLC那么就只加载旧的包,这样的缺点也很明显,就是所有的东西都被杂糅到了新包里面。更好的方式是依旧按照之前的方式分类,新的角色模型打入一个新包,新的场景打入另一个新包,这样玩家既可以不用下载之前的内容,又可以很好地分类。 -
类型分组:
将相似的资源分配到一个包,比如音频在一个包,动画在一个包,模型在一个包等 -
并发内容分组:
将需要同时加载和使用的资源捆绑在一起,这种方式就是基于关卡的,比如这个关卡有一些特殊的东西,而其他关卡都没有的,那么就把这些特殊的东西打在一起。
遵循原则
- 将频繁更新的对象拆分为AssetBundle,与很少更改的对象分开
- 对可能同时加载的对象进行分 组。例如模型,纹理和动画。
- 如果您注意到多个AssetBundle中的多个对象依赖于来自完全不同的AssetBundle的单个资产,请将依赖项移动到单独的AssetBundle。如果多个AssetBundle引用其他AssetBundle中的同一组资产,则可能值得将这些依赖项拉入共享AssetBundle以减少重复。
- 如果不可能同时加载两组对象,例如标准和高清属性,请确保它们位于自己的AssetBundle中。
- 如果同时经常加载50%的捆绑包,请考虑拆分AssetBundle。
- 考虑组合小型(少于5到10个资产)但其内容经常同时加载的AssetBundle。
- 如果一组对象只是同一对象的不同版本,请考虑AssetBundle Variants。
本文部分内容引用字Unity官方文档