Unity AssetBundle详解

简介

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

AB包的创建

AssetBundles Browser 打包工具

下载安装

GitHub下载地址:GitHub - Unity-Technologies/AssetBundles-Browser: Editor tool for viewing and debugging asset bundle contents before and after builds

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}");
    }
}
相关推荐
一步一个foot-print10 小时前
【Unity】Light Probe 替代点光源给环境动态物体加光照
unity·游戏引擎
@LYZY11 小时前
Unity 中隐藏文件规则
unity·游戏引擎·游戏程序·vr
霜绛13 小时前
C#知识补充(二)——命名空间、泛型、委托和事件
开发语言·学习·unity·c#
Sator116 小时前
使用Unity ASE插件设置数值不会生效的问题
unity·游戏引擎
程序猿追17 小时前
轻量级云原生体验:在OpenEuler 25.09上快速部署单节点K3s
人工智能·科技·机器学习·unity·游戏引擎
B0URNE18 小时前
【Unity基础详解】(7)Unity核心:动画系统
unity·游戏引擎
我的golang之路果然有问题18 小时前
mac M系列芯片 unity 安装会遇到的错误以及解决
经验分享·学习·macos·unity·游戏引擎
Hody912 天前
【XR开发系列】2025 年 XR 开发入门,我该选择 Unity 还是 Unreal Engine?
unity·xr·虚幻
DvLee10242 天前
UnityGLTF 材质创建与赋值流程
unity·材质
HahaGiver6662 天前
从0到1做一个“字母拼词”Unity小游戏(含源码/GIF)- 字母拼词正确错误判断
unity·游戏引擎·游戏程序