[Unity] AssetBundle 资源管理和更新

904 阅读4分钟

如果找不到 Asset Bundle Browser

AB 包官方文档:

docs.unity3d.com/2020.1/Docu…

如果在 Unity 的 package manager 中没找到 Asset Bundle Browser,可以到他官方文档给出的 git 中下载


我是看的视频:

www.bilibili.com/video/BV135…

1. 使用 Asset Bundle Browser 打包

拖动要打包的资源到 Asset Bundle Browser 窗口

图片.png

然后点击 Build 选项就可以得到打包文件

2. 加载 AB 包

加载场景:

void LoadSceneAB() {
        //注意 assetBundleName 和 sceneName 可能不同,一个是 AssetBundle 的名字,一个是 Scene 的名字
        string assetBundleName = "keshengsquare.unity3d";
        string sceneName = "KeshengSquare";
        string path = Application.dataPath + "/StreamingAssets/" + assetBundleName;

        var myLoadedAssetBundle = AssetBundle.LoadFromFile(path);

        if (myLoadedAssetBundle != null)
        {
            SceneManager.LoadScene(sceneName);
        }
    }

加载实例:

void LoadAssetAB() {
    //注意 assetBundleName 和 assetName 可能不同,一个是 AssetBundle 的名字,一个是 Asset 的名字
    string assetBundleName = "keshengsquare.unity3d";
    string assetName = "KeshengSquare";
    string path = Application.dataPath + "/StreamingAssets/" + assetBundleName;

    var myLoadedAssetBundle = AssetBundle.LoadFromFile(path);

    if (myLoadedAssetBundle != null)
    {
        var assetObj = myLoadedAssetBundle.LoadAsset<GameObject>(assetName);
        MonoBehaviour.Instantiate(assetObj);
    }
}

3. 设置依赖包

如果两个 AB 包之间有重复的部分,那么就相当于一个资源打包了多次,就会浪费空间

在 Asset Bundle Browser 会自动提示哪些包之间有重复,然后可以右键选择创建依赖包

图片.png

这个创建依赖包不是说创建出来之后就万事大吉了,他也只是一个 AB 包而已,你原来的两个 AB 包之间的重复的部分被移动到这个新的 AB 包里面了(后面会看到不止是重复的部分)。

但是如果你不加载这个新的 AB 包,也就是说,你原来已经写好了加载两个 AB 包,但之后不写新的代码加载这个新的 AB 包的话,你原来的两个 AB 包就会丢失掉那些被移动到新 AB 包的内容。

所以还需要一个代码来加载依赖包

blog.csdn.net/weixin_4834…

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
 
public class Load : MonoBehaviour
{//处理依赖关系的加载,必须加载主AB包,因为依赖关系都存储在主AB包中
    
    void Start()
    {
        //加载主AB包(不是ab文件夹,是ab文件!)
        AssetBundle main = AssetBundle.LoadFromFile("主AB包‘路径’(无后缀名)");
 
        //获取AB包的配置文件
        AssetBundleManifest manifest = main.LoadAsset<AssetBundleManifest>("AssetBundleManifest");
 
        //分析预制体所在AB包,依赖哪些AB包
        string [] deps= manifest.GetAllDependencies("预制体AB包‘名’(无后缀名)");
       
        
        //加载依赖的AB包
        for(int i=0;i<deps.Length;i++)
        {
            AssetBundle.LoadFromFile("存放所有文件夹的路径/" + deps[i]);
        }
 
        //加载预制体所在的AB包
        AssetBundle imageab= AssetBundle.LoadFromFile("预制体AB包路径(无后缀名)");
 
 
        //加载预制体(内部资源)
        GameObject prefab = imageab.LoadAsset<GameObject>("预制体名字");
 
        //附:
        //实例化
        GameObject gob = Instantiate(prefab);
        //设置父物体
        gob.transform.SetParent(GameObject.Find("/Canvas").transform);
    }
}

4. 依赖包的优化

依赖包会包括重复的两个包中,所有可能重复的部分

比如依赖包是这样子的,由于角色用到了若干个动画,而一个动画对应一个动作模型,也就是有多个模型

图片.png

但是实际上角色只用到了一个模型

图片.png

优化方法就是

  1. 角色动画不包含模型

    这个要在动画制作的时候就调好,需要动画制作注意

  2. 在打包之前,就在 Unity 中,把每个动画对应的多余的动作模型删除,只留下动画片段

  3. 从根本上让两个 AB 包之间没有重复

    比如一开始是打包场景和角色,场景中含有角色,所以两个包有重复,那现在在 Unity 场景中先删去角色,然后再打包,场景和角色的 AB 包就没有重复了,然后在游戏过程中动态添加角色

5. 分包设计

如果有很多角色,是把所有角色都放到一个 AB 包里面,做替换更新,还是将不同角色放到不同 AB 包里面,做增量更新?

显然是后者比较好

同时在加密的过程中,每次加密解密也需要耗时,大的 AB 包解密更耗时

6. 资源加载框架

6.1 防止多次加载 AB 包

blog.csdn.net/Q540670228/…

//AB包缓存---解决AB包无法重复加载的问题 也有利于提高效率。
private Dictionary<string, AssetBundle> abCache;

...

//加载AB包
private AssetBundle LoadABPackage(string abName)
{
    AssetBundle ab;
    //加载ab包,需一并加载其依赖包。
    if (mainAB == null)
    {
        //根据各个平台下的基础路径和主包名加载主包
        mainAB = AssetBundle.LoadFromFile(basePath + mainABName);
        //获取主包下的AssetBundleManifest资源文件(存有依赖信息)
        mainManifest = mainAB.LoadAsset<AssetBundleManifest>("AssetBundleManifest");
    }
    //根据manifest获取所有依赖包的名称 固定API
    string[] dependencies = mainManifest.GetAllDependencies(abName);
    //循环加载所有依赖包
    for (int i = 0; i < dependencies.Length; i++)
    {
        //如果不在缓存则加入
        if (!abCache.ContainsKey(dependencies[i]))
        {
            //根据依赖包名称进行加载
            ab = AssetBundle.LoadFromFile(basePath + dependencies[i]);
            //注意添加进缓存 防止重复加载AB包
            abCache.Add(dependencies[i], ab);
        }
    }
    //加载目标包 -- 同理注意缓存问题
    if (abCache.ContainsKey(abName)) return abCache[abName];
    else
    {
        ab = AssetBundle.LoadFromFile(basePath + abName);
        abCache.Add(abName, ab);
        return ab;
    }
}

6.2 区分编辑器模式和打包模式

编辑器模式下不使用 AB 包加载资源,这样就可以快速测试,不需要我每次新增一个资源都要打包,可以等到我测试好了,修改好了之后,再切换到打包模式,打包模式下资源的加载使用 AB 包