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}");
    }
}
相关推荐
mxwin7 小时前
Unity Shader 半透明物体为什么不能写入深度缓冲?
unity·游戏引擎·shader
晚枫歌F9 小时前
三层时间轮的实现
网络·unity·游戏引擎
咸鱼永不翻身10 小时前
Lua脚本事件检查工具
unity·lua·工具
leo__52012 小时前
单载波中继系统资源分配算法MATLAB仿真程序
算法·matlab·unity
努力长头发的程序猿13 小时前
Unity使用ScriptableObject序列化资源
unity·游戏引擎
mxwin13 小时前
Unity Shader 手写基于 PBR 的 URP Lit Shader 核心光照计算
unity·游戏引擎·shader
小贺儿开发13 小时前
Unity3D 智能云端数字标牌系统
unity·阿里云·人机交互·视频·oss·广告·互动
魔士于安14 小时前
Unity windows 同步 异步 打开文件文件夹工具
游戏·unity·游戏引擎·贴图·模型
魔士于安14 小时前
unity lowpoly 风格 城市 建筑 道路 交通标志
游戏·unity·游戏引擎·贴图·模型
mxwin14 小时前
Unity GPU Shader 性能优化指南
unity·游戏引擎·shader