Unity AssetBundles资源加载管理器

发布于:2025-03-17 ⋅ 阅读:(16) ⋅ 点赞:(0)

Unity AssetBundles资源加载管理器

实现了AB包管理器
目的: 让外部更方便地进行资源加载(同步加载/异步加载)

技术包含:

  1. AB包相关API
  2. 单例模式
  3. 委托(Lambda)表达式
  4. 协程
  5. 字典

AssetBundles工具下载地址

using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.Events;


/// <summary>
/// AB 包管理器
/// 目的: 让外部更方便地进行资源加载
/// 包含
/// 1. AB包相关API
/// 2. 单例模式
/// 3. 委托(Lambda)表达式
/// 4. 协程
/// 5. 字典
/// </summary>
public class ABMgr : SingletonAutoMono<ABMgr>
{

    //主包
    private AssetBundle mainAB = null;
    //依赖包获取的配置文件
    private AssetBundleManifest manifest= null;

    //字典  用字典来存储 加载过的AB包
    private Dictionary<string, AssetBundle> abDic = new Dictionary<string, AssetBundle>();

    //AB包存放路径
    private string PathUrl
    {
        get
        {
            return Application.streamingAssetsPath+"/";
        }
    }

    //主包名
    private string MainABName
    {
        get
        {
            #if UNITY_IOS
                    return "IOS";
            #elif UNITY_ANDROID
                    return "Android";
            #else
                    return "PC";
            #endif


        }
    }
    /// <summary>
    /// 加载ab包
    /// </summary>
    /// <param name="abname"></param>

    private void LoadAB(string abname)
    {
        //加载AB包
        if (mainAB == null)
        {
            mainAB = AssetBundle.LoadFromFile(PathUrl + MainABName);
            manifest = mainAB.LoadAsset<AssetBundleManifest>("AssetBundleManifest");
        }
        //获取abname包的依赖信息,根据依赖信息添加依赖包
        AssetBundle ab = null;
        string[] strs = manifest.GetAllDependencies(abname);
        for (int i = 0; i < strs.Length; i++)
        {
            //判断包是否加载过了
            if (!abDic.ContainsKey(strs[i]))
            {
                ab = AssetBundle.LoadFromFile(PathUrl + strs[i]);
                abDic.Add(strs[i], ab);
            }
        }
        //加载资源来源包,如果没有加载过再加载
        if (!abDic.ContainsKey(abname))
        {
            ab = AssetBundle.LoadFromFile(PathUrl + abname);
            abDic.Add(abname, ab);
        }
    }
    //同步加载 根据名字
    public Object LoadRes(string abname,string resname)
    {
        //加载ab包
        LoadAB(abname);

        //加载资源
        //为了方便外面加载 判断资源是否为GameObect
        //如果是 直接实例化 再返回给外部
        Object obj = abDic[abname].LoadAsset(resname);
        if (obj is GameObject)
        {
            return Instantiate(obj);
        }
        else return obj;
    }

    //同步加载 根据type
    public Object LoadRes(string abname, string resname,System.Type type)
    {
        //加载ab包
        LoadAB(abname);

        //加载资源
        //为了方便外面加载 判断资源是否为GameObect
        //如果是 直接实例化 再返回给外部
        Object obj = abDic[abname].LoadAsset(resname,type);
        if (obj is GameObject)
        {
            return Instantiate(obj);
        }
        else return obj;
    }

    //同步加载 泛型
    public T LoadRes<T>(string abname, string resname) where T: Object
    {
        //加载ab包
        LoadAB(abname);

        //加载资源
        //为了方便外面加载 判断资源是否为GameObect
        //如果是 直接实例化 再返回给外部
        T obj = abDic[abname].LoadAsset<T>(resname);
        if (obj is GameObject)
        {
            return Instantiate(obj);
        }
        else return obj;
    }

    /// <summary>
    /// 异步加载(Async) 根据名字
    /// 加载AB包没有使用异步
    /// 而是加载AB包中的asset资源的时候使用异步
    /// </summary>
    /// <param name="abname"></param>
    public void LoadResAsync(string abname, string resname,UnityAction<Object> callBack)
    {
       
        StartCoroutine(ReallyLoadAsync(abname,resname,callBack));
    }
   
    private IEnumerator ReallyLoadAsync(string abname,string resname,UnityAction<Object> callBack)
    {
        //加载AB包
        LoadAB(abname);

        //创建请求 从AB包加载资源
        AssetBundleRequest abr = abDic[abname].LoadAssetAsync(resname);
      
        //等待abr加载结束
        yield return abr;
        //abr.asset 为加载的资源
        if(abr.asset is GameObject)
        {
            //abr如果是GameObject 实例化
            callBack(Instantiate(abr.asset));
        }else
        {
            callBack(abr.asset);
        }

    }

    /// <summary>
    /// 异步加载(Async) 根据type
    /// </summary>
    /// <param name="abname"></param>

    public void LoadResAsync(string abname, string resname,System.Type type, UnityAction<Object> callBack)
    {

        StartCoroutine(ReallyLoadAsync(abname, resname,type, callBack));
    }

    private IEnumerator ReallyLoadAsync(string abname, string resname, System.Type type,UnityAction<Object> callBack)
    {
        //加载AB包
        LoadAB(abname);

        //创建请求 从AB包加载资源
        AssetBundleRequest abr = abDic[abname].LoadAssetAsync(resname,type);

        //等待abr加载结束
        yield return abr;
        //abr.asset 为加载的资源
        if (abr.asset is GameObject)
        {
            //abr如果是GameObject 实例化
            callBack(Instantiate(abr.asset));
        }
        else
        {
            callBack(abr.asset);
        }

    }


    /// <summary>
    /// 异步加载(Async) 泛型
    /// </summary>
    /// <param name="abname"></param>
    public void LoadResAsync<T>(string abname, string resname, UnityAction<T> callBack) where T : Object 
    {
		
		// public delegate void UnityAction<T0>(T0 arg0);
		//其中UnityAciton是有着一个参数(T0)的委托
        StartCoroutine(ReallyLoadAsync<T>(abname, resname, callBack));
    }

    private IEnumerator ReallyLoadAsync<T>(string abname, string resname, UnityAction<T> callBack) where T: Object 
    {
        //加载AB包
        LoadAB(abname);
	
        //创建请求 从AB包加载资源
        AssetBundleRequest abr = abDic[abname].LoadAssetAsync<T>(resname);

        //等待abr加载结束
        yield return abr;
        //abr.asset 为加载的资源
        if (abr.asset is GameObject)
        {
            //abr如果是GameObject 实例化
            //最后回调函数(函数指针,函数作为参数)调用委托
            callBack(Instantiate(abr.asset) as T);
        }
        else
        {
            callBack(abr.asset as T);
        }

    }

    //单个包卸载
    public void Unload(string abname)
    {
        if (abDic.ContainsKey(abname))
        {
            abDic[abname].Unload(false);
            abDic.Remove(abname);
        }
    }
    //所有包卸载
    public void ClearAB()
    {
        //卸载所有AssetBundles(UnloadAll)
        AssetBundle.UnloadAllAssetBundles(false);
        //清空字典
        abDic.Clear();
        //主包和配置文件置空
        mainAB = null;
        manifest = null;
    }

}