boxmoe_header_banner_img

菜就多练喵

文章导读

[Unity]热更新 03 AB包资源加载管理器


avatar
Ib_Mccf 2026年1月13日 19
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;

public class ABMgr : MonoBehaviour
{
    public static ABMgr Instance;

    private void Awake()
    {
        if (Instance == null)
            Instance = this;
        else
            Destroy(gameObject);
    }

    private void OnDestroy()
    {
        if (Instance == this)
            Instance = null;
    }

    //AB包路径
    private string PathURL => Application.streamingAssetsPath + "/";

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

    /// <summary>
    /// 主包
    /// </summary>
    private AssetBundle mainAB = null;

    /// <summary>
    /// AB包依赖信息
    /// </summary>
    private AssetBundleManifest manifest = null;

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

    /// <summary>
    /// 加载AB包
    /// </summary>
    /// <param name="assetBundleName"></param>
    /// <returns></returns>
    public Object LoadRes(string abName, string resName)
    {
        LoadAB(abName);
        //加载资源
        var res = abDic[abName].LoadAsset(resName);
        if (res is GameObject) return Instantiate(res);
        return res;
    }

    public Object LoadRes(string abName, string resName, System.Type type)
    {
        LoadAB(abName);
        //加载资源
        var res = abDic[abName].LoadAsset(resName, type);
        if (res is GameObject) return Instantiate(res);
        return res;
    }

    public T LoadRes<T>(string abName, string resName) where T : Object
    {
        LoadAB(abName);
        //加载资源
        var res = abDic[abName].LoadAsset<T>(resName);
        if (res is GameObject) return Instantiate(res);
        return res;
    }

    private void LoadAB(string abName)
    {
        //加载主包
        if (mainAB == null)
        {
            mainAB = AssetBundle.LoadFromFile(PathURL + MainABName);
            manifest = mainAB.LoadAsset<AssetBundleManifest>("AssetBundleManifest");
        }

        //加载依赖AB包
        string[] dependencies = manifest.GetAllDependencies(abName);
        foreach (var dependency in dependencies)
        {
            if (!abDic.ContainsKey(dependency))
            {
                var ab = AssetBundle.LoadFromFile(PathURL + dependency);
                abDic.Add(dependency, ab);
            }
        }

        //加载资源AB包
        if (!abDic.ContainsKey(abName))
        {
            var resAB = AssetBundle.LoadFromFile(PathURL + abName);
            abDic.Add(abName, resAB);
        }
    }
    
    /// <summary>
    /// 异步加载AB包中的资源,通过委托返回资源
    /// </summary>
    /// <param name="abName"></param>
    /// <param name="resName"></param>
    /// <param name="callback"></param>
    public void LoadResAsync(string abName, string resName, UnityAction<Object> callback)
    {
        StartCoroutine(ReallyLoadResAsync(abName, resName, callback));
    }

    private IEnumerator ReallyLoadResAsync(string abName, string resName, UnityAction<Object> callback)
    {
        LoadAB(abName);
        //加载资源
        AssetBundleRequest abr = abDic[abName].LoadAssetAsync(resName);
        yield return abr;
        if (abr.asset is GameObject) callback(Instantiate(abr.asset));
        else callback(abr.asset);
    }
    
    public void LoadResAsync(string abName, string resName, System.Type type, UnityAction<Object> callback)
    {
        StartCoroutine(ReallyLoadResAsync(abName, resName, callback));
    }

    private IEnumerator ReallyLoadResAsync(string abName, string resName, System.Type type, UnityAction<Object> callback)
    {
        LoadAB(abName);
        //加载资源
        AssetBundleRequest abr = abDic[abName].LoadAssetAsync(resName, type);
        yield return abr;
        if (abr.asset is GameObject) callback(Instantiate(abr.asset));
        else callback(abr.asset);
    }
    
    public void LoadResAsync<T>(string abName, string resName, UnityAction<T> callback) where T : Object
    {
        StartCoroutine(ReallyLoadResAsync<T>(abName, resName, callback));
    }

    private IEnumerator ReallyLoadResAsync<T>(string abName, string resName, UnityAction<T> callback) where T : Object
    {
        LoadAB(abName);
        //加载资源
        AssetBundleRequest abr = abDic[abName].LoadAssetAsync<T>(resName);
        yield return abr;
        if (abr.asset is GameObject) callback(Instantiate(abr.asset) as T);
        else callback(abr.asset as T);
    }
    public void Unload(string abName)
    {
        if (abDic.TryGetValue(abName, out AssetBundle ab))
        {
            ab.Unload(false);
            abDic.Remove(abName);
        }
    }

    public void ClearAB()
    {
        AssetBundle.UnloadAllAssetBundles(false);
        abDic.Clear();
        mainAB = null;
        manifest = null;
    }
}


评论(0)

查看评论列表

暂无评论


发表评论

表情 颜文字

插入代码