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}");
    }
}
相关推荐
一只一只1 小时前
Unity 3D笔记——《B站阿发你好》
笔记·3d·unity
SmalBox6 小时前
【光照】[PBR][法线分布]GGX实现方法对比
unity·渲染
UWA7 小时前
游戏在高负载场景下,整机功耗控制在多少
游戏·unity·性能优化·游戏开发
软件黑马王子17 小时前
2025GUI项目实践:Unity编辑模式下GUI运行
游戏·unity·gui
王源骏18 小时前
Unity实现网页端 打开本地文件选择图片上传到阿里云的OSS
unity·阿里云·游戏引擎
爱吃小胖橘19 小时前
Unity-角色控制器
3d·unity·c#·游戏引擎
绀目澄清1 天前
unity3d PuppetMaster 布娃娃插件在学习
unity
PaoloBanchero1 天前
Unity 虚拟仿真实验中设计模式的使用 ——状态模式(State Pattern)
unity·设计模式·状态模式
SmalBox1 天前
【光照】[PBR][镜面反射]实现方法解析
unity·渲染
Robbie丨Yang1 天前
【Unity 入门教程】四、如何制作一个 Perfab
unity·游戏引擎