5.AB包资源管理器

5.AB包资源管理器


5.1 知识点

创建AssetBundleManager类,实现单例

/// <summary>
/// AssetBundle管理器
/// </summary>
public class AssetBundleManager : BaseSingletonInMonoBehaviour<AssetBundleManager>
{
}

定义AB主包,清单,AB包字典,AB包文件夹路径,AB主包名变量

private AssetBundle mainAssetBundle = null; // 主 AssetBundle
private AssetBundleManifest assetBundleManifest = null; // AssetBundle 清单
private Dictionary<string, AssetBundle> assetBundleDictionary = new Dictionary<string, AssetBundle>(); // AssetBundle 字典

/// <summary>
/// 获取 AssetBundle 文件夹的路径
/// </summary>
private string assetBundleFolderPath
{
    get
    {
        return Application.streamingAssetsPath + "/";
    }
}

/// <summary>
/// 获取主 AssetBundle 的名称
/// </summary>
private string mainAssetBundleName
{
    get
    {
#if UNITY_IOS
        return "IOS";
#elif UNITY_ANDROID
        return "Android";
#else
        return "PC";
#endif
    }
}

定义加载目标包、依赖包、主包、清单文件的方法,方便同步加载和异步加载时的使用

/// <summary>
/// 加载主 AssetBundle 和 AssetBundle 清单
/// </summary>
private void LoadMainAssetBundleAndAssetBundleManifest()
{
    if (mainAssetBundle == null)
    {
        mainAssetBundle = AssetBundle.LoadFromFile(assetBundleFolderPath + mainAssetBundleName);
        assetBundleManifest = mainAssetBundle.LoadAsset<AssetBundleManifest>("AssetBundleManifest");
    }
}

/// <summary>
/// 加载 AssetBundle 的依赖项
/// </summary>
private void LoadAssetBundleDependencies(string assetBundleName)
{
    LoadMainAssetBundleAndAssetBundleManifest();

    string[] strs = assetBundleManifest.GetAllDependencies(assetBundleName);
    for (int i = 0; i < strs.Length; i++)
    {
        if (!assetBundleDictionary.ContainsKey(strs[i]))
        {
            AssetBundle ab = AssetBundle.LoadFromFile(assetBundleFolderPath + strs[i]);
            assetBundleDictionary.Add(strs[i], ab);
        }
    }
}

/// <summary>
/// 加载目标 AssetBundle
/// </summary>
private void LoadAssetBundleTarget(string assetBundleName)
{
    if (!assetBundleDictionary.ContainsKey(assetBundleName))
    {
        AssetBundle assetBundle = AssetBundle.LoadFromFile(assetBundleFolderPath + assetBundleName);
        assetBundleDictionary.Add(assetBundleName, assetBundle);
    }
}

/// <summary>
/// 加载目标 AssetBundle 和其依赖项
/// </summary>
private void LoadAssetBundleTargetAndDependencies(string assetBundleName)
{
    LoadAssetBundleDependencies(assetBundleName);
    LoadAssetBundleTarget(assetBundleName);
}

同步加载资源,如果是游戏对象就实例化

/// <summary>
/// 如果资源是 GameObject,则实例化;否则返回原始资源
/// </summary>
private T InstantiateIfGameObject<T>(T resource) where T : Object
{
    if (resource is GameObject)
    {
        return Instantiate(resource);
    }
    else
    {
        return resource;
    }
}

/// <summary>
/// 同步加载 AssetBundle 中的资源
/// </summary>
public T LoadAssetBundleResource<T>(string assetBundleName, string resourceName) where T : Object
{
    LoadAssetBundleTargetAndDependencies(assetBundleName);

    T resource = assetBundleDictionary[assetBundleName].LoadAsset<T>(resourceName);

    return InstantiateIfGameObject<T>(resource);
}

/// <summary>
/// 同步加载 AssetBundle 中的资源,指定资源类型
/// </summary>
public Object LoadAssetBundleResource(string assetBundleName, string resourceName, System.Type type)
{
    LoadAssetBundleTargetAndDependencies(assetBundleName);

    Object resource = assetBundleDictionary[assetBundleName].LoadAsset(resourceName, type);

    return InstantiateIfGameObject(resource);
}

/// <summary>
/// 同步加载 AssetBundle 中的资源
/// </summary>
public Object LoadAssetBundleResource(string assetBundleName, string resourceName)
{
    LoadAssetBundleTargetAndDependencies(assetBundleName);

    Object resource = assetBundleDictionary[assetBundleName].LoadAsset(resourceName);

    return InstantiateIfGameObject(resource);
}

异步加载资源,如果是游戏对象就实例化且执行回调

/// <summary>
/// 如果资源是 GameObject,则实例化后执行回调;否则直接执行回调
/// </summary>
private void InstantiateIfGameObjectAndCallBack<T>(T resource, UnityAction<T> callBack) where T : Object
{
    if (resource is GameObject)
        callBack(Instantiate(resource) as T);
    else
        callBack(resource as T);
}

/// <summary>
/// 异步加载 AssetBundle 中的资源
/// </summary>
public void LoadAssetBundleResourceAsync<T>(string assetBundleName, string resourceName, UnityAction<T> callBack) where T : Object
{
    StartCoroutine(LoadAssetBundleResourceAsyncCoroutine<T>(assetBundleName, resourceName, callBack));
}

private IEnumerator LoadAssetBundleResourceAsyncCoroutine<T>(string assetBundleName, string resourceName, UnityAction<T> callBack) where T : Object
{
    LoadAssetBundleTargetAndDependencies(assetBundleName);

    AssetBundleRequest assetBundleRequest = assetBundleDictionary[assetBundleName].LoadAssetAsync<T>(resourceName);
    yield return assetBundleRequest;

    InstantiateIfGameObjectAndCallBack<T>(assetBundleRequest.asset as T, callBack);
}

/// <summary>
/// 异步加载 AssetBundle 中的资源,指定资源类型
/// </summary>
public void LoadAssetBundleResourceAsync(string assetBundleName, string resourceName, System.Type type, UnityAction<Object> callBack)
{
    StartCoroutine(LoadAssetBundleResourceAsyncCoroutine(assetBundleName, resourceName, type, callBack));
}

private IEnumerator LoadAssetBundleResourceAsyncCoroutine(string assetBundleName, string resourceName, System.Type type, UnityAction<Object> callBack)
{
    LoadAssetBundleTargetAndDependencies(assetBundleName);

    AssetBundleRequest assetBundleRequest = assetBundleDictionary[assetBundleName].LoadAssetAsync(resourceName, type);
    yield return assetBundleRequest;

    InstantiateIfGameObjectAndCallBack(assetBundleRequest.asset, callBack);
}

/// <summary>
/// 异步加载 AssetBundle 中的资源
/// </summary>
public void LoadAssetBundleResourceAsync(string assetBundleName, string resourceName, UnityAction<Object> callBack)
{
    StartCoroutine(LoadAssetBundleResourceAsyncCoroutine(assetBundleName, resourceName, callBack));
}

private IEnumerator LoadAssetBundleResourceAsyncCoroutine(string assetBundleName, string resourceName, UnityAction<Object> callBack)
{
    LoadAssetBundleTargetAndDependencies(assetBundleName);

    AssetBundleRequest assetBundleRequest = assetBundleDictionary[assetBundleName].LoadAssetAsync(resourceName);
    yield return assetBundleRequest;

    InstantiateIfGameObjectAndCallBack(assetBundleRequest.asset, callBack);
}

卸载指定包和所有包

/// <summary>
/// 卸载指定名称的 AssetBundle
/// </summary>
public void UnLoadAssetBundle(string name)
{
    if (assetBundleDictionary.ContainsKey(name))
    {
        assetBundleDictionary[name].Unload(false);
        assetBundleDictionary.Remove(name);
    }
}

/// <summary>
/// 清理所有 AssetBundle
/// </summary>
public void ClearAssetBundle()
{
    AssetBundle.UnloadAllAssetBundles(false);
    assetBundleDictionary.Clear();
    mainAssetBundle = null;
    assetBundleManifest = null;
}

进行测试

AssetBundleManager.Instance.LoadAssetBundleResource<GameObject>("model", "cube");
AssetBundleManager.Instance.LoadAssetBundleResource<GameObject>("model", "sphere");
AssetBundleManager.Instance.LoadAssetBundleResourceAsync<GameObject>("model", "sphere", (sphere) =>
{
    sphere.GetComponent<Renderer>().material = AssetBundleManager.Instance.LoadAssetBundleResource<Material>("icon", "红色");
    sphere.transform.position = new Vector3(2, 2, 2);
});


5.2 知识点代码

AssetBundleManager

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

/// <summary>
/// AssetBundle管理器
/// </summary>
public class AssetBundleManager : BaseSingletonInMonoBehaviour<AssetBundleManager>
{
    #region 变量

    private AssetBundle mainAssetBundle = null; // 主 AssetBundle
    private AssetBundleManifest assetBundleManifest = null; // AssetBundle 清单
    private Dictionary<string, AssetBundle> assetBundleDictionary = new Dictionary<string, AssetBundle>(); // AssetBundle 字典

    /// <summary>
    /// 获取 AssetBundle 文件夹的路径
    /// </summary>
    private string assetBundleFolderPath
    {
        get
        {
            return Application.streamingAssetsPath + "/";
        }
    }

    /// <summary>
    /// 获取主 AssetBundle 的名称
    /// </summary>
    private string mainAssetBundleName
    {
        get
        {
#if UNITY_IOS
            return "IOS";
#elif UNITY_ANDROID
            return "Android";
#else
            return "PC";
#endif
        }
    }

    #endregion

    #region 加载包

    /// <summary>
    /// 加载主 AssetBundle 和 AssetBundle 清单
    /// </summary>
    private void LoadMainAssetBundleAndAssetBundleManifest()
    {
        if (mainAssetBundle == null)
        {
            mainAssetBundle = AssetBundle.LoadFromFile(assetBundleFolderPath + mainAssetBundleName);
            assetBundleManifest = mainAssetBundle.LoadAsset<AssetBundleManifest>("AssetBundleManifest");
        }
    }

    /// <summary>
    /// 加载 AssetBundle 的依赖项
    /// </summary>
    private void LoadAssetBundleDependencies(string assetBundleName)
    {
        LoadMainAssetBundleAndAssetBundleManifest();

        string[] strs = assetBundleManifest.GetAllDependencies(assetBundleName);
        for (int i = 0; i < strs.Length; i++)
        {
            if (!assetBundleDictionary.ContainsKey(strs[i]))
            {
                AssetBundle ab = AssetBundle.LoadFromFile(assetBundleFolderPath + strs[i]);
                assetBundleDictionary.Add(strs[i], ab);
            }
        }
    }

    /// <summary>
    /// 加载目标 AssetBundle
    /// </summary>
    private void LoadAssetBundleTarget(string assetBundleName)
    {
        if (!assetBundleDictionary.ContainsKey(assetBundleName))
        {
            AssetBundle assetBundle = AssetBundle.LoadFromFile(assetBundleFolderPath + assetBundleName);
            assetBundleDictionary.Add(assetBundleName, assetBundle);
        }
    }

    /// <summary>
    /// 加载目标 AssetBundle 和其依赖项
    /// </summary>
    private void LoadAssetBundleTargetAndDependencies(string assetBundleName)
    {
        LoadAssetBundleDependencies(assetBundleName);
        LoadAssetBundleTarget(assetBundleName);
    }

    #endregion

    #region 同步加载

    /// <summary>
    /// 如果资源是 GameObject,则实例化;否则返回原始资源
    /// </summary>
    private T InstantiateIfGameObject<T>(T resource) where T : Object
    {
        if (resource is GameObject)
        {
            return Instantiate(resource);
        }
        else
        {
            return resource;
        }
    }

    /// <summary>
    /// 同步加载 AssetBundle 中的资源
    /// </summary>
    public T LoadAssetBundleResource<T>(string assetBundleName, string resourceName) where T : Object
    {
        LoadAssetBundleTargetAndDependencies(assetBundleName);

        T resource = assetBundleDictionary[assetBundleName].LoadAsset<T>(resourceName);

        return InstantiateIfGameObject<T>(resource);
    }

    /// <summary>
    /// 同步加载 AssetBundle 中的资源,指定资源类型
    /// </summary>
    public Object LoadAssetBundleResource(string assetBundleName, string resourceName, System.Type type)
    {
        LoadAssetBundleTargetAndDependencies(assetBundleName);

        Object resource = assetBundleDictionary[assetBundleName].LoadAsset(resourceName, type);

        return InstantiateIfGameObject(resource);
    }

    /// <summary>
    /// 同步加载 AssetBundle 中的资源
    /// </summary>
    public Object LoadAssetBundleResource(string assetBundleName, string resourceName)
    {
        LoadAssetBundleTargetAndDependencies(assetBundleName);

        Object resource = assetBundleDictionary[assetBundleName].LoadAsset(resourceName);

        return InstantiateIfGameObject(resource);
    }

    #endregion

    #region 异步加载

    /// <summary>
    /// 如果资源是 GameObject,则实例化后执行回调;否则直接执行回调
    /// </summary>
    private void InstantiateIfGameObjectAndCallBack<T>(T resource, UnityAction<T> callBack) where T : Object
    {
        if (resource is GameObject)
            callBack(Instantiate(resource) as T);
        else
            callBack(resource as T);
    }

    /// <summary>
    /// 异步加载 AssetBundle 中的资源
    /// </summary>
    public void LoadAssetBundleResourceAsync<T>(string assetBundleName, string resourceName, UnityAction<T> callBack) where T : Object
    {
        StartCoroutine(LoadAssetBundleResourceAsyncCoroutine<T>(assetBundleName, resourceName, callBack));
    }

    /// <summary>
    /// 异步加载 AssetBundle 中的资源,指定资源类型
    /// </summary>
    private IEnumerator LoadAssetBundleResourceAsyncCoroutine<T>(string assetBundleName, string resourceName, UnityAction<T> callBack) where T : Object
    {
        LoadAssetBundleTargetAndDependencies(assetBundleName);

        AssetBundleRequest assetBundleRequest = assetBundleDictionary[assetBundleName].LoadAssetAsync<T>(resourceName);
        yield return assetBundleRequest;

        InstantiateIfGameObjectAndCallBack<T>(assetBundleRequest.asset as T, callBack);
    }

    /// <summary>
    /// 异步加载 AssetBundle 中的资源,指定资源类型
    /// </summary>
    public void LoadAssetBundleResourceAsync(string assetBundleName, string resourceName, System.Type type, UnityAction<Object> callBack)
    {
        StartCoroutine(LoadAssetBundleResourceAsyncCoroutine(assetBundleName, resourceName, type, callBack));
    }

    /// <summary>
    /// 异步加载 AssetBundle 中的资源
    /// </summary>
    private IEnumerator LoadAssetBundleResourceAsyncCoroutine(string assetBundleName, string resourceName, System.Type type, UnityAction<Object> callBack)
    {
        LoadAssetBundleTargetAndDependencies(assetBundleName);

        AssetBundleRequest assetBundleRequest = assetBundleDictionary[assetBundleName].LoadAssetAsync(resourceName, type);
        yield return assetBundleRequest;

        InstantiateIfGameObjectAndCallBack(assetBundleRequest.asset, callBack);
    }

    /// <summary>
    /// 异步加载 AssetBundle 中的资源
    /// </summary>
    public void LoadAssetBundleResourceAsync(string assetBundleName, string resourceName, UnityAction<Object> callBack)
    {
        StartCoroutine(LoadAssetBundleResourceAsyncCoroutine(assetBundleName, resourceName, callBack));
    }

    /// <summary>
    /// 异步加载 AssetBundle 中的资源
    /// </summary>
    private IEnumerator LoadAssetBundleResourceAsyncCoroutine(string assetBundleName, string resourceName, UnityAction<Object> callBack)
    {
        LoadAssetBundleTargetAndDependencies(assetBundleName);

        AssetBundleRequest assetBundleRequest = assetBundleDictionary[assetBundleName].LoadAssetAsync(resourceName);
        yield return assetBundleRequest;

        InstantiateIfGameObjectAndCallBack(assetBundleRequest.asset, callBack);
    }

    #endregion

    #region 卸载包

    /// <summary>
    /// 卸载指定名称的 AssetBundle
    /// </summary>
    public void UnLoadAssetBundle(string name)
    {
        if (assetBundleDictionary.ContainsKey(name))
        {
            assetBundleDictionary[name].Unload(false);
            assetBundleDictionary.Remove(name);
        }
    }

    /// <summary>
    /// 清理所有 AssetBundle
    /// </summary>
    public void ClearAssetBundle()
    {
        AssetBundle.UnloadAllAssetBundles(false);
        assetBundleDictionary.Clear();
        mainAssetBundle = null;
        assetBundleManifest = null;
    }

    #endregion
}

Lesson05_AB包资源管理器

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

public class Lesson05_AB包资源管理器 : MonoBehaviour
{
    void Start()
    {
        AssetBundleManager.Instance.LoadAssetBundleResource<GameObject>("model", "cube");
        AssetBundleManager.Instance.LoadAssetBundleResource<GameObject>("model", "sphere");
        AssetBundleManager.Instance.LoadAssetBundleResourceAsync<GameObject>("model", "sphere",(sphere) =>
        {
            sphere.GetComponent<Renderer>().material = AssetBundleManager.Instance.LoadAssetBundleResource<Material>("icon", "红色");
            sphere.transform.position = new Vector3(2,2,2);
        });
    }
}


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com

×

喜欢就点赞,疼爱就打赏