目的:让外部更方便的进行资源加载。
首先身为管理者,我们只需要一个。因此要创建一个单例。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//C#中 泛型知识点
//设计模式 单例模式的知识点
//继承这种自动创建的 单例模式基类 不需要我们手动去拖 或者 api去加了
//想用他 直接 GetInstance就行了
public class SingletonAutoMono<T> : MonoBehaviour where T : MonoBehaviour
{
private static T instance;
public static T GetInstance()
{
if( instance == null )
{
GameObject obj = new GameObject();
//设置对象的名字为脚本名
obj.name = typeof(T).ToString();
//让这个单例模式对象 过场景 不移除
//因为 单例模式对象 往往 是存在整个程序生命周期中的
DontDestroyOnLoad(obj);
instance = obj.AddComponent<T>();
}
return instance;
}
}
然后创建 ABManager去继承它。
public class ABManager : SingletonAutoMono<ABManager>
开始添加属性、方法等。
AB包加载文件分5步:
第一步 加载AB包(主包)
第二步 根据主包获取依赖包
第三步 获取依赖包相关信息
第四步 判断是否加载过来源包
第五步 加载资源
那么开始了:
首先我们需要定义三个属性,分别为主包、依赖包获取用的配置文件、以及一个用来判断包是否导入的字典。
//主包
private AssetBundle mainAB = null;
//依赖包获取用的配置文件
private AssetBundleManifest manifest = null;
//AB包不能够重复加载 重复会报错
//字典 用字典来存储加载过的AB包
private Dictionary<string, AssetBundle> abDic = new Dictionary<string, AssetBundle>();
在加载AB包时我们需要用到AB包的路径。AB包的名字是不确定的,但是AB包的路径前一部分是确定的,那就是AB包的资源是在Asset路径下的。
/// <summary>
/// 这是AB包存放路径 方便修改
/// </summary>
private string PathURL
{
get
{
return Application.streamingAssetsPath + "/";
}
}
当我们在不同平台时,打包出的主包可能不同,因此也定义一个属性,方便修改。
/// <summary>
/// 主包名 方便修改
/// </summary>
private string MainABName
{
get
{
#if UNITY_IOS
return "IOS"
#elif UNITY_ANDROID
return "Android"
#else
return "PC";
#endif
}
}
经过以上重重的准备,我们可以准备加载了:
/// <summary>
/// 加载AB包
/// </summary>
/// <param name="name"></param>
public void LoadAB (string abName)
{
//加载AB主包
if (mainAB == null)
{
mainAB = AssetBundle.LoadFromFile(PathURL + MainABName);
manifest = mainAB.LoadAsset<AssetBundleManifest>("AssetBundleManifest");
}
//我们获取依赖包相关信息
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)
{
LoadAB(abName);
//为了外面方便加载资源时 判断资源是否是GameObject
//如果是 则直接生成。,
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)
{
LoadAB(abName);
//为了外面方便加载资源时 判断资源是否是GameObject
//如果是 则直接生成。,
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
{
LoadAB(abName);
//为了外面方便加载资源时 判断资源是否是GameObject
//如果是 则直接生成。,
T obj = abDic[abName].LoadAsset<T>(resName);
if (obj is GameObject)
return Instantiate(obj);
else
return obj;
}
//异步加载的方法
/// <summary>
/// 名字 异步加载 指定资源
/// </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);
//加载目标包
if (!abDic.ContainsKey(abName))
{
AssetBundle ab = AssetBundle.LoadFromFile(PathURL + abName);
abDic.Add(abName, ab);
}
//异步加载包中资源
AssetBundleRequest abq = abDic[abName].LoadAssetAsync(resName);
yield return abq;
if (abq.asset is GameObject)
callBack(Instantiate(abq.asset));
else
callBack(abq.asset);
}
/// <summary>
/// Type异步加载资源
/// </summary>
/// <param name="abName"></param>
/// <param name="resName"></param>
/// <param name="type"></param>
/// <param name="callBack"></param>
public void LoadResAsync(string abName, string resName, System.Type type, UnityAction<Object> callBack)
{
StartCoroutine(ReallyLoadResAsync(abName, resName, type, callBack));
}
private IEnumerator ReallyLoadResAsync(string abName, string resName, System.Type type, UnityAction<Object> callBack)
{
//加载依赖包
LoadAB(abName);
//加载目标包
if (!abDic.ContainsKey(abName))
{
AssetBundle ab = AssetBundle.LoadFromFile(PathURL + abName);
abDic.Add(abName, ab);
}
//异步加载包中资源
AssetBundleRequest abq = abDic[abName].LoadAssetAsync(resName, type);
yield return abq;
if (abq.asset is GameObject)
callBack(Instantiate(abq.asset));
else
callBack(abq.asset);
}
/// <summary>
/// 泛型异步加载资源
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="abName"></param>
/// <param name="resName"></param>
/// <param name="callBack"></param>
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);
//加载目标包
if (!abDic.ContainsKey(abName))
{
AssetBundle ab = AssetBundle.LoadFromFile(PathURL + abName);
abDic.Add(abName, ab);
}
//异步加载包中资源
AssetBundleRequest abq = abDic[abName].LoadAssetAsync<T>(resName);
yield return abq;
if (abq.asset is GameObject)
callBack(Instantiate(abq.asset) as T);
else
callBack(abq.asset as T);
}