AB package manager_AB_Manager

Based on the existing API, the AB package manager is organized to make it easier to load resources.

Four functions are provided: synchronous loading, asynchronous loading, single package uninstallation, and all package uninstallation.

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

public class AB_Manager : SingletonAutoMono<AB_Manager>
{
    
    
    //!==============AB包管理器 目的是 更方便的进行资源的加载================
    //!========提供四个功能:分别是 同步加载 异步加载 单个包卸载 所有包卸载

    //>记录下主包 因为主包只需要加载一次 避免每次加载一个依赖包都需要进行加载主包的重复操作
    private AssetBundle mainAB = null;
    //>记录主包的mainfest文件 用于获取依赖包的信息 
    private AssetBundleManifest manifest = null;

    //>AB包不能重复加载 重复加载会报错
    //用字典来记录 加载过的AB包 避免重复加载
    private Dictionary<string, AssetBundle> abDic = new Dictionary<string, AssetBundle>();

    /// <summary>
    /// >AB包打包后的输出路径 (拷贝到streamingAssetsPath文件夹)
    /// </summary>
    /// <value></value>
    private string PathUrl
    {
    
    
        get
        {
    
    
            return Application.streamingAssetsPath + "/";
        }
    }

    //>主包路径 不同平台位置不同 
    private string MainABPath
    {
    
    
        get
        {
    
    
#if UNITY_IOS
            return "IOS";
#elif UNITY_ANDROID
            return "Android";
#else
            return "AB_Path";
#endif
        }
    }

    /// <summary>
    /// >加载目标AB包_以及该包的相关依赖包信息_加载后会存储在字典中
    /// </summary>
    /// <param name="abName"></param>
    public void LoadAB_And_Dependencies(string abName)
    {
    
    
        #region 1.先从主包中加载资源包依赖相关
        //加载主包 再从主包中加载mainfest文件
        if (mainAB == null)
        {
    
    
            mainAB = AssetBundle.LoadFromFile(PathUrl + MainABPath);
            manifest = mainAB.LoadAsset<AssetBundleManifest>("AssetBundleManifest");
        }
        //临时变量 用于存储加载后的包
        //>因为所有包加载后就会添加到字典当中 所有用临时变量来存储
        AssetBundle ab = null;
        //>从主包中的mainfest文件中 得到目标AB包的所有依赖包的包名
        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);
            }
        }
        #endregion

        #region 2.加载完依赖后,再加载目标资源包
        //如果字典中没有 就加载
        if (!abDic.ContainsKey(abName))
        {
    
    
            ab = AssetBundle.LoadFromFile(PathUrl + abName);
            abDic.Add(abName, ab);
        }
        #endregion
    }

    #region 同步加载资源

    /// <summary>
    /// 同步加载资源_(1) 不指定类型
    /// </summary>
    /// <param name="abName">ab包名</param>
    /// <param name="resName">ab包资源名</param>
    /// <returns></returns>
    public Object LoadRes(string abName, string resName)
    {
    
    
        LoadAB_And_Dependencies(abName);
        //加载完所有包后 再从包中加载资源
        Object obj = abDic[abName].LoadAsset(resName);
        return obj;

        //>可选: 如果资源是个游戏对象 就直接实例化后再返回
        // if (obj is GameObject)
        //     return Instantiate(obj);
        // else
        //     return obj;
        //>>>>>>>>>>>>>>>>>>>>>>>>>>>>
    }

    /// <summary>
    /// 同步加载资源_(2)_type加载指定类型
    /// 避免同名不同类型资源加载时的问题
    /// </summary>
    /// <param name="type">加载的资源类型</param>
    /// <returns></returns>
    public Object LoadRes(string abName, string resName, System.Type type)
    {
    
    
        LoadAB_And_Dependencies(abName);
        return abDic[abName].LoadAsset(resName, type);
    }

    /// <summary>
    /// 同步加载资源_(3)_泛型加载指定类型
    /// 返回值和指定类型一致
    /// </summary>
    /// <typeparam name="T">加载的资源类型</typeparam>
    /// <returns></returns>
    public T LoadRes<T>(string abName, string resName) where T : Object
    {
    
    
        LoadAB_And_Dependencies(abName);
        return abDic[abName].LoadAsset<T>(resName);
    }
    #endregion

    #region 异步加载资源
    //>TODO:这里只是实现了异步加载了AB包中的资源 并没有实现异步加载AB包
    //开启协程
    public void LoadResAsyncStart(string abName, string resName, UnityAction<object> callBack)
    {
    
    
        StartCoroutine(LoadResAsync(abName, resName, callBack));
    }

    public IEnumerator LoadResAsync(string abName, string resName, UnityAction<object> callBack)
    {
    
    
        LoadAB_And_Dependencies(abName);//加载目标包和相关依赖
        //>异步加载包中资源
        //返回值类型是协程的 AssetBundleRequest
        AssetBundleRequest abr = abDic[abName].LoadAssetAsync(resName);
        yield return abr;
        //异步加载结束后 通过委托回调 实例化并返回
        if (abr.asset is GameObject)
        {
    
    
            callBack(Instantiate(abr.asset));
        }
        else
        {
    
    
            callBack(abr.asset);
        }
    }

    //1.Type指定
    public void LoadResAsyncStart(string abName, string resName, System.Type type, UnityAction<object> callBack)
    {
    
    
        StartCoroutine(LoadResAsync(abName, resName, callBack));
    }

    public IEnumerator LoadResAsync(string abName, string resName, System.Type type, UnityAction<object> callBack)
    {
    
    
        LoadAB_And_Dependencies(abName);
        AssetBundleRequest abr = abDic[abName].LoadAssetAsync(resName, type);
        yield return abr;
        //异步加载结束后 通过委托价格加载的资源返回出去
        if (abr.asset is GameObject)
        {
    
    
            callBack(Instantiate(abr.asset));
        }
        else
        {
    
    
            callBack(abr.asset);
        }
    }
    //2.泛型指定
    public void LoadResAsyncStart<T>(string abName, string resName, UnityAction<T> callBack) where T : Object
    {
    
    
        StartCoroutine(LoadResAsync<T>(abName, resName, callBack));
    }

    public IEnumerator LoadResAsync<T>(string abName, string resName, UnityAction<T> callBack) where T : Object
    {
    
    
        LoadAB_And_Dependencies(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);
        }
    }
    #endregion

    //单个包卸载
    public void AB_UnLoadSingle(string abName)
    {
    
    
        if (abDic.ContainsKey(abName))
        {
    
    
            abDic[abName].Unload(false);
            abDic.Remove(abName);
        }
    }

    //所有包卸载
    public void AB_CleraAll()
    {
    
    
        AssetBundle.UnloadAllAssetBundles(false);
        //同时将这些容器都清空
        abDic = null;
        mainAB = null;
        manifest = null;
    }
}



Guess you like

Origin blog.csdn.net/m0_69778537/article/details/134588239