简介
AssetBundle(简称:AB包) 是 Unity 提供的一种资源压缩包,用于在应用运行时动态地加载和卸载资源。它可以将非代码资源(如模型、纹理、预制体、音频、甚至整个场景)打包成一个或多个文件,这些文件可以存放在本地或远程服务器上。(不支持打包C#脚本)

AB包的创建
AssetBundles Browser 打包工具
下载安装
1、在Unity工程中创建文件夹Editor

2、将删除资源包中Tests文件夹后放入到Editor文件夹中

3、确认是否安装成功
打开Window=>AssetBundle Browser

资源打包
1、标记资源
选中资源,在Inspector面板进行Assetbundle标记。可以自定义包名和资源扩展名。AssetBundle的名字固定为小写,如果在名字中使用了大写字母,系统会自动转换为小写格式。另外,每个AssetBundle都可以设置一个扩展名。如果需要区别素材,可使用扩展名来加以区分。要添加子文件夹,请用 / 分隔文件夹名称。例如,使用 AssetBundle 名称 environment/forest 在 environment 子文件夹下创建名为 forest 的捆绑包。

2、资源设置
打开AssetBundle Browser窗口,可以看见已经标记过的AB包信息

3、了解Bulid面板

|-----------------------------|--------------------------------------------------------------------------------------------------------------------------------|
| 参数 | 描述 |
| Build Target | 选择面向什么平台打包 |
| Output Path | AssetBundle打包后的输出路径 |
| Clear Folders | 指打包前是否将Output Path中的文件清空 |
| Copy to StreamingAssets | 将Output path中的文件复制到Unity StreamingAssets文件夹中 |
| Compression | No Compression 不压缩,解压快,但是AssetBundle包大 LZMA 压缩大小最小,但是解压慢,如果需要AB包中一个资源,会将所有资源进行解压 LZ4压缩大小会比LZMA大,但是用什么资源就解压什么资源(推荐) |
4、点击Build按钮,进行资源构建

每一个AssetBundle资源将会有一个和文件相关的".mainfest"文件,该文件提供了所打包资源的CRC和资源依赖的信息。还有两个文件(StandaloneWindows),记录整个AssetBundle文件夹的信息,包括资源列表及各个列表之间的依赖关系。
自定义工具(使用AB包构建API)
输出路径一般情况下为Assets下的某一个文件夹,该文件夹不会自动创建,需要玩家在运行前手动创建,否则会报错
cs
[MenuItem("项目工具/AssetBundle/构建AB包资源")]
public static void BuildAssetBundleLogic()
{
BuildPipeline.BuildAssetBundles("Assets/AssetBundles", BuildAssetBundleOptions.None,
BuildTarget.StandaloneWindows);
}
加载AB包
AssetBundle不能够重复加载,否则报错
|----------------------------------------------|--------------------------|
| 方法 | 描述 |
| AssetBundle.LoadFromFile | 从磁盘上的文件同步加载 AssetBundle。 |
| AssetBundle.LoadAsset(string name) | 从捆绑包中加载名为 name 的资源。 |
| AssetBundle.LoadAsset<T>(string name) | 从捆绑包中加载名为 name 的资源。 |
| AssetBundle.LoadAsset(string name,Type type) | 从捆绑包中加载名为 name 的资源。 |
| AssetBundle.LoadAllAssets | 加载AssetBundle中所有资源对象 |
| AssetBundle.LoadAllAssetsAsync | 异步加载AssetBundle中所有资源togn |
为了便于测试,将打包后的AB包放到StreamingAssets文件夹中,实际开发时可以自己指定路径。
同步加载
cs
public Image icon;
void Start()
{
var abPath=Path.Combine(Application.streamingAssetsPath,"role.game");
//先加载AB包
var ab = AssetBundle.LoadFromFile(abPath);
//从AB包中加载指定资源
var sprite = ab.LoadAsset<Sprite>("迪希雅");
icon.sprite = sprite;
}
异步加载
cs
StartCoroutine(LoadABRes("role.game", "迪希雅", (obj) =>
{
if (obj is Sprite sprite)
{
icon.sprite = sprite;
}
}));
/// <summary>
/// 异步加载AB包中的资源
/// </summary>
/// <param name="abName">ab包名称</param>
/// <param name="resName">资源名称</param>
/// <param name="callback">成功加载后回调</param>
/// <returns></returns>
IEnumerator LoadABRes(string abName, string resName,Action<object> callback)
{
//加载ab包
var ab = AssetBundle.LoadFromFileAsync(Application.streamingAssetsPath + "/" + abName);
yield return ab;
//从ab包中加载资源
var asset = ab.assetBundle.LoadAssetAsync(resName, typeof(Sprite));
yield return asset;
callback?.Invoke(asset.asset);
}
卸载AB包
|--------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------|
| 方法 | 描述 |
| Unload (bool unloadAllLoadedObjects); 有异步方法 | 卸载 AssetBundle 释放其数据。 当 unloadAllLoadedObjects 为 false 时,只卸载ab包,不清除已加载的资源 当为 true 时,不仅卸载ab包,还会清除已加载的资源引用 |
| AssetBundle.UnloadAllAssetBundles(bool unloadAllObjects) 无异步方法 | 卸载当前已加载的所有 AssetBundle。 unloadAllObjects的true/false规则同上 |
cs
private void UnloadAssetBundle(string abName)
{
var list = AssetBundle.GetAllLoadedAssetBundles().ToList();
for (var i = 0; i < list.Count; i++)
{
var ab = list[i];
if (ab.name == abName)
{
ab.Unload(true);
break;
}
}
}
注意
资源依赖问题
这是 AB 系统中最复杂也最容易出问题的部分。
如果包 A 中的预制体使用了包 B 中的材质,那么包 A 就依赖于包 B。加载包 A 中的预制体前,必须确保包 B 中的材质已经被加载到内存中。
cs
//加载依赖资源
private void LoadDependRes(string abName)
{
//加载主包
var abMain = AssetBundle.LoadFromFile($"{Application.streamingAssetsPath}/StandaloneWindows");
//加载主包中的固定文件
var abManifest = abMain.LoadAsset<AssetBundleManifest>("AssetBundleManifest"); //从固定文件中,得到依赖信息
var strs = abManifest.GetAllDependencies(abName);
//得到了依赖包的名字
foreach (var item in strs)
{
AssetBundle.LoadFromFile($"{Application.streamingAssetsPath}/{item}");
}
}