using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System;
using UnityEngine.Networking;
public enum E_AssetBundleLoadType
{
///
/// www方式异步加载
///
WWW = 0,
///
/// LoadFromFile方式异步加载
///
LoadFromFileAsync = 1,
///
/// LoadFromFile方式同步加载
///
LoadFromFileSynchro = 2,
///
/// 网络加载
///
NetUrlMode = 3,
///
/// 新版资源包加载方式
///
NewAssetBundle = 4,
}
///
/// 资源管理器
/// By WJ 2019-12-12 09:03:30
///
public class ResourceHelper : MonoSingleton
{
///
/// 正在加载的相同AssetBundle列表
///
private Dictionary>> mSameAssetBundleAcList = new Dictionary>>();
///
/// 已加载的AssetBundle
///
private Dictionary mAssetBundleList = new Dictionary();
///
/// 正在加载的资源名称列表
///
private List mLoadingAssetList = new List();
///
/// 加载进度
///
private float mLoadProgress = 0;
///
/// 超时时间
///
private float mTimeOutTime = 0;
#region 新版加载方式
///
/// 主文件
///
private AssetBundleManifest abManifest = null;
///
/// 主文件请求
///
private AssetBundle manifesAssetBundle = null;
///
/// 资源包的请求
///
private Dictionary loadNewAssetBundles = new Dictionary();
///
/// 资源包后缀
///
private static string AssetBundleSuffix = ".unity3d";
#endregion
/////
///// 加载资源
/////
///// 名称
///// 加载完成后的回调
///// 同一文件是否支持多重加载,false时同一时间只会加载一份
///// 加载的类型,默认LoadFromFile异步加载
//public void LoadAssetBundle(string _name, Action ac, bool multiLoad = true, E_AssetBundleLoadType type = E_AssetBundleLoadType.LoadFromFileAsync)
//{
// switch (type)
// {
// case E_AssetBundleLoadType.WWW:
// LoadAssetBundleWWW(_name, ac, multiLoad);
// break;
// case E_AssetBundleLoadType.LoadFromFileAsync:
// LoadAssetBundleAsync(_name, ac, multiLoad);
// break;
// case E_AssetBundleLoadType.LoadFromFileSynchro:
// LoadAssetBundleSynchro(_name, ac);
// break;
// //case E_AssetBundleLoadType.NetUrlMode:
// // LoadAssetBundleUrl(_name, ac);
// // break;
// //case E_AssetBundleLoadType.NewAssetBundle:
// // LoadAssetBundleNew(_name, ac);
// // break;
// }
//}
///
/// 新版加载资源包
///
/// 所属类型名称
/// 加载的资源名称
/// 加载完成的回调
public void LoadAssetBundle(string resName, Action ac = null)
{
if (string.IsNullOrEmpty(resName))
{
return;
}
string assetBundleName = resName.ToLower() + AssetBundleSuffix;
string mainPath = GetNewPath("", "");
if (manifesAssetBundle == null)
{
manifesAssetBundle = AssetBundle.LoadFromFile(mainPath + "NewRes");
}
// 加载主文件
if (abManifest == null)
{
abManifest = manifesAssetBundle.LoadAsset("assetbundlemanifest");
}
var hash = abManifest.GetAssetBundleHash(assetBundleName);
// 新版资源,查找依赖
if (hash.isValid)
{
Debug.Log(resName+"存在依赖关系,使用新版加载方式");
// 再查找依赖资源包加载并创建
string[] strs = abManifest.GetAllDependencies(assetBundleName);
foreach (var itemName in strs)
{
if (loadNewAssetBundles.ContainsKey(itemName) == false)
{
try
{
AssetBundle ylAssetBundle = AssetBundle.LoadFromFile(mainPath + itemName);
loadNewAssetBundles.Add(itemName, ylAssetBundle);
}
catch (Exception e)
{
UI_CueDialog.Instance().Open("加载异常:" + e.Message);
}
}
}
}
// 旧版资源包,用正常名称
else
{
Debug.Log(resName + "不存在依赖关系,使用旧版加载方式");
assetBundleName = resName + AssetBundleSuffix;
}
if (loadNewAssetBundles.ContainsKey(assetBundleName) == false)
{
// 最后再加载并创建自身资源包
AssetBundle ab = AssetBundle.LoadFromFile(mainPath + assetBundleName);
loadNewAssetBundles.Add(assetBundleName, ab);
if (ac == null)
{
GameObject go = ab.LoadAsset(resName);
if (go != null)
{
Instantiate(go);
}
}
else
{
ac(ab);
}
}
else
{
AssetBundle ab = loadNewAssetBundles[assetBundleName];
if (ac == null)
{
GameObject go = ab.LoadAsset(resName);
if (go != null)
{
Instantiate(go);
}
}
else
{
ac(ab);
}
}
}
///
/// 获取加载进度
///
///
public float GetLoadProgress()
{
return mLoadProgress;
}
/////
///// 加载网络资源
/////
/////
/////
/////
//private void LoadAssetBundleUrl(string _name, Action ac)
//{
// if (_name == string.Empty)
// {
// ac(null);
// return;
// }
// if (mAssetBundleList.ContainsKey(_name))
// {
// ac(mAssetBundleList[_name]);
// }
// else
// {
// if (mLoadingAssetList.Contains(_name) == false)
// {
// mLoadingAssetList.Add(_name);
// StartCoroutine(IELoadAssetBundleUrl(_name, ac));
// }
// else
// {
// if (mSameAssetBundleAcList.ContainsKey(_name))
// {
// if (mSameAssetBundleAcList[_name].Contains(ac) == false)
// {
// mSameAssetBundleAcList[_name].Add(ac);
// }
// }
// else
// {
// List> acList = new List>();
// acList.Add(ac);
// mSameAssetBundleAcList.Add(_name, acList);
// }
// }
// }
//}
/////
///// 协同加载网络资源
/////
/////
/////
/////
/////
//IEnumerator IELoadAssetBundleUrl(string _name, Action ac, string fileSuffix = ".unity3d")
//{
// // 重新加载
// bool reLoad = true;
// while (reLoad)
// {
// string url = "";
// uint version = 0;
// string streamingAssetsPath = Application.streamingAssetsPath + "/Res/" + _name + fileSuffix;
// if (Launcher.netUpdateFileInfo != null)
// {
// if (Application.isEditor && File.Exists(streamingAssetsPath))
// {
// url = "file://" + streamingAssetsPath;
// }
// else
// {
// if (RuntimePlatform.IPhonePlayer == Application.platform)
// {
// url = Launcher.netUrl + "UpdateAndroid/" + _name + fileSuffix;
// }
// else
// {
// url = Launcher.netUrl + "UpdateAndroid/" + _name + fileSuffix;
// }
// }
// foreach (FileMD5Info info in Launcher.netUpdateFileInfo.Infos)
// {
// if (info.Name == _name + fileSuffix)
// {
// if(info.PackSizeM >= 1)
// {
// UI_LoadingWindow.Instance().Show(1);
// }
// version = (uint)info.PackVersion;
// break;
// }
// }
// }
// else
// {
// version = Launcher.netVersion;
// }
// UnityWebRequest request = null;
// // 编辑器下,有工程资源,不走缓存机制
// if (Application.isEditor && File.Exists(streamingAssetsPath))
// {
// request = UnityWebRequestAssetBundle.GetAssetBundle(url);
// }
// else
// {
// request = UnityWebRequestAssetBundle.GetAssetBundle(url, version, 0);
// }
// yield return request.SendWebRequest();
// // 加载完成,移除正在加载的资源
// mLoadingAssetList.Remove(_name);
// // 等待加载完成
// while (request.isDone == false)
// {
// yield return new WaitForSeconds(0.05f);
// }
// // 没有错误
// if (request.error == null)
// {
// AssetBundle ab = (request.downloadHandler as DownloadHandlerAssetBundle).assetBundle;
// mAssetBundleList.Add(_name, ab);
// if (ac != null)
// {
// ac(ab);
// }
// reLoad = false;
// // 关闭Loading
// if (mLoadingAssetList.Count == 0)
// {
// UI_LoadingWindow.Instance().Hide(1);
// }
// // 返回相同AC
// if (mSameAssetBundleAcList.ContainsKey(_name))
// {
// for (int i = 0; i < mSameAssetBundleAcList[_name].Count; i++)
// {
// mSameAssetBundleAcList[_name][i](ab);
// }
// mSameAssetBundleAcList[_name].Clear();
// }
// }
// else
// {
// bool waiting = false;
// if (request.isNetworkError)
// {
// // 不可写入
// if (request.error == "Unable to write data")
// {
// reLoad = false;
// }
// else
// {
// reLoad = true;
// waiting = true;
// UI_CueDialog.Instance().Open("加载" + _name + " 失败,是否重试?", "", E_DialogType.TwoBntton, () =>
// {
// // 同意的回调
// waiting = false;
// }, () =>
// {
// // 取消的回调
// Application.Quit();
// });
// }
// }
// else if (request.isHttpError)
// {
// reLoad = true;
// waiting = true;
// UI_CueDialog.Instance().Open("加载" + _name + " 失败,是否重试?", "", E_DialogType.TwoBntton, () =>
// {
// // 同意的回调
// waiting = false;
// }, () =>
// {
// // 取消的回调
// Application.Quit();
// });
// }
// Debug.LogError(_name + " 加载错误: " + request.error);
// while (waiting)
// {
// yield return new WaitForSeconds(0.1f);
// }
// // 不重新加载,则返回回调
// if (reLoad == false)
// {
// if (ac != null)
// {
// ac(null);
// }
// // 关闭Loading
// UI_LoadingWindow.Instance().Hide(1);
// }
// }
// }
//}
///
/// WWW加载AssetBundle
///
/// 名称,不包含后缀
/// Lambda返回值
private void LoadAssetBundleWWW(string _name, Action ac, bool multiLoad = true)
{
if (_name == string.Empty)
{
ac(null);
return;
}
if (mAssetBundleList.ContainsKey(_name))
{
ac(mAssetBundleList[_name]);
}
else
{
if (mLoadingAssetList.Contains(_name) == false)
{
mLoadingAssetList.Add(_name);
StartCoroutine(IELoadAssetBundleWWW(_name, ac, multiLoad));
}
else
{
if (mSameAssetBundleAcList.ContainsKey(_name))
{
if (mSameAssetBundleAcList[_name].Contains(ac) == false)
{
mSameAssetBundleAcList[_name].Add(ac);
}
}
else
{
List> acList = new List>();
acList.Add(ac);
mSameAssetBundleAcList.Add(_name, acList);
}
}
}
}
///
/// 协同加载AssetBundle
///
/// 名称,不包含后缀
/// Lambda返回值
/// 返回资源AssetBundle
private IEnumerator IELoadAssetBundleWWW(string _name, Action ac, bool multiLoad = true)
{
WWW www = new WWW(GetPath(_name));
yield return www;
// 加载完成
mLoadingAssetList.Remove(_name);
if (www != null && www.assetBundle != null)
{
mAssetBundleList.Add(_name, www.assetBundle);
ac(www.assetBundle);
// 返回相同AC
if (mSameAssetBundleAcList.ContainsKey(_name))
{
for (int i = 0; i < mSameAssetBundleAcList[_name].Count; i++)
{
if (multiLoad)
{
mSameAssetBundleAcList[_name][i](www.assetBundle);
}
}
mSameAssetBundleAcList[_name].Clear();
}
}
else
{
ac(null);
// 返回相同AC
if (mSameAssetBundleAcList.ContainsKey(_name))
{
for (int i = 0; i < mSameAssetBundleAcList[_name].Count; i++)
{
if (multiLoad)
{
mSameAssetBundleAcList[_name][i](null);
}
}
mSameAssetBundleAcList[_name].Clear();
}
Debug.LogWarning("没有找到资源__" + _name);
}
}
///
/// 同步读取资源
///
/// 资源名称(不带后缀)
/// Object
private void LoadAssetBundleSynchro(string _name, Action ac)
{
if (string.IsNullOrEmpty(_name))
{
ac(null);
return;
}
String path = GetPath2(_name);
if (mAssetBundleList.ContainsKey(_name))
{
ac(mAssetBundleList[_name]);
}
else
{
AssetBundle ab = AssetBundle.LoadFromFile(path);
if (ab != null)
{
mAssetBundleList.Add(_name, ab);
ac(ab);
}
else
{
ac(null);
}
}
}
///
/// 异步读取资源
///
/// 名称,不包含后缀
/// Lambda返回值(必须经过实例化才可用)
private void LoadAssetBundleAsync(string _name, Action ac, bool multiLoad = true)
{
if (string.IsNullOrEmpty(_name))
{
ac(null);
return;
}
if (mAssetBundleList.ContainsKey(_name))
{
ac(mAssetBundleList[_name]);
}
else
{
if (mLoadingAssetList.Contains(_name) == false)
{
mLoadingAssetList.Add(_name);
StartCoroutine(IELoadAssetBundleAsync(_name, ac, multiLoad));
}
else
{
if (mSameAssetBundleAcList.ContainsKey(_name))
{
if (mSameAssetBundleAcList[_name].Contains(ac) == false)
{
mSameAssetBundleAcList[_name].Add(ac);
}
}
else
{
List> acList = new List>();
acList.Add(ac);
mSameAssetBundleAcList.Add(_name, acList);
}
}
}
}
///
/// 协同加载AssetBundle
///
/// 名称,不包含后缀
/// Lambda返回值
/// 返回资源AssetBundle
private IEnumerator IELoadAssetBundleAsync(string _name, Action ac, bool multiLoad = true)
{
String path = GetPath2(_name);
AssetBundleCreateRequest abcRequest = AssetBundle.LoadFromFileAsync(path);
// 等待加载完成
while (abcRequest != null && abcRequest.isDone == false)
{
mLoadProgress = abcRequest.progress;
yield return new WaitForSeconds(0.015f);
}
mLoadProgress = 1.0f;
// 加载完成
mLoadingAssetList.Remove(_name);
if (abcRequest != null && abcRequest.assetBundle != null)
{
mAssetBundleList.Add(_name, abcRequest.assetBundle);
ac(abcRequest.assetBundle);
// 返回相同AC
if (mSameAssetBundleAcList.ContainsKey(_name))
{
for (int i = 0; i < mSameAssetBundleAcList[_name].Count; i++)
{
if (multiLoad)
{
mSameAssetBundleAcList[_name][i](abcRequest.assetBundle);
}
}
mSameAssetBundleAcList[_name].Clear();
}
}
else
{
ac(null);
// 返回相同AC
if (mSameAssetBundleAcList.ContainsKey(_name))
{
for (int i = 0; i < mSameAssetBundleAcList[_name].Count; i++)
{
mSameAssetBundleAcList[_name][i](null);
}
mSameAssetBundleAcList[_name].Clear();
}
Debug.LogWarning("没有找到资源__" + _name);
}
}
///
/// 加载外部纯文本 by:jgao
///
/// url路径
/// 回调
/// 数据
public void LoadText(string strName, Action ac, Dictionary postData = null)
{
if (strName == string.Empty)
{
return;
}
StartCoroutine(IELoadText(strName, ac, postData));
}
///
/// 加载外部纯文本 by:jgao
///
/// 名称
/// 回调
/// 数据
/// 返回资源AssetBundle
private IEnumerator IELoadText(string name, Action ac, Dictionary postData)
{
WWW www;
if (postData == null)
{
www = new WWW(name);
}
else
{
WWWForm form = new WWWForm();
foreach (KeyValuePair kv in postData)
{
form.AddField(kv.Key, kv.Value);
}
www = new WWW(name, form);
}
DateTime timer = DateTime.MinValue;
float lastProgress = 0.0f;
// 超时检测(苹果支付时不考虑超时问题)
while (false == www.isDone && postData == null)
{
if (www.error != null)
{
Debug.LogWarning("网络超时,请检查网络后重试!");
yield break;
}
if (www.progress.Equals(0))
{
if (lastProgress.Equals(0) && timer == DateTime.MinValue)
{
lastProgress = www.progress;
timer = DateTime.Now;
}
else
{
double diff = (DateTime.Now - timer).TotalMilliseconds;
if (diff > Const.NetDefaultTimeOut)
{
Debug.LogWarning("网络超时,请检查网络后重试!");
yield break;
}
}
}
else
{
// 进度值一直不动,超过10s认为断网
if (www.progress.Equals(lastProgress))
{
double diff = (DateTime.Now - timer).TotalMilliseconds;
if (diff > Const.NetDefaultTimeOut)
{
Debug.LogWarning("网络超时,请检查网络后重试!");
yield break;
}
}
else
{
// 正常下载,重置状态
lastProgress = www.progress;
timer = DateTime.Now;
}
}
yield return null;
}
yield return www;
if (www.error == null)
{
ac(www.text);
www.Dispose();
}
else
{
Debug.LogWarning(www.error);
}
}
///
/// 卸载AssetBundle
///
/// 名称,不包含后缀
/// 强力卸载,为真时即便是常驻内存也将被卸载
/// 是否卸载成功
public bool UnloadAssetBundle(string _name)
{
if (mAssetBundleList.ContainsKey(_name))
{
mAssetBundleList[_name].Unload(true);
mAssetBundleList.Remove(_name);
return true;
}
return false;
}
///
/// 清除所有AssetBundle
///
/// 强力卸载,为真时即便是常驻内存也将被卸载
public void ClearAllAssetBundle()
{
List KeyList = new List(mAssetBundleList.Keys);
for (int i = 0; i < KeyList.Count; i++)
{
UnloadAssetBundle(KeyList[i]);
}
}
///
/// 获取异步加载资源路径(用于 www 加载)
///
/// 资源名称
/// 文件后缀
/// 返回实际路径
public static string GetPath(string strName, string fileSuffix = ".unity3d")
{
string strPath = string.Empty;
string persistentDataPath = Application.persistentDataPath + "/Res/" + strName + fileSuffix;
string streamingAssetsPath = Application.streamingAssetsPath + "/Res/" + strName + fileSuffix;
if (Application.isEditor)
{
if (File.Exists(streamingAssetsPath))
{
strPath = "file://" + streamingAssetsPath;
}
else
{
strPath = "file:///" + persistentDataPath;
}
}
else
{
if (File.Exists(persistentDataPath))
{
strPath = "file://" + persistentDataPath;
}
else
{
if (RuntimePlatform.Android == Application.platform)
{
strPath = streamingAssetsPath;
}
else
{
strPath = "file://" + streamingAssetsPath;
}
}
}
return strPath;
}
///
/// 获取加载资源路径(用于 LoadFromFile 的同步和异步加载)
///
/// 资源名称
/// 文件后缀
/// 返回实际路径
public static string GetPath2(string strName, string fileSuffix = ".unity3d")
{
string path = "";
string persistentDataPath = Application.persistentDataPath + "/Res/" + strName + fileSuffix;// 沙盒路径
string streamingAssetsPath = Application.streamingAssetsPath + "/Res/" + strName + fileSuffix;
if (Application.isEditor)
{
if (File.Exists(streamingAssetsPath))
{
path = streamingAssetsPath;
}
else
{
path = persistentDataPath;
}
}
else
{
if (File.Exists(persistentDataPath))
{
path = persistentDataPath;
}
else
{
if (RuntimePlatform.Android == Application.platform)
{
path = Application.dataPath + "!assets" + "/Res/" + strName + fileSuffix;
}
else
{
path = streamingAssetsPath;
}
}
}
return path;
}
///
/// 获取加载资源路径(用于 LoadFromFile 的同步和异步加载)
///
/// 资源名称
/// 文件后缀
/// 返回实际路径
public static string GetNewPath(string strName, string fileSuffix = ".unity3d")
{
string path = "";
//string persistentDataPath = Application.persistentDataPath + "/NewRes/" + strName + fileSuffix;// 沙盒路径
string streamingAssetsPath = Application.streamingAssetsPath + "/NewRes/" + strName + fileSuffix;
if (Application.isEditor)
{
//if (File.Exists(streamingAssetsPath))
{
path = streamingAssetsPath;
}
//else
//{
// path = persistentDataPath;
//}
}
else
{
//if (File.Exists(persistentDataPath))
//{
// path = persistentDataPath;
//}
//else
{
if (RuntimePlatform.Android == Application.platform)
{
path = Application.dataPath + "!assets" + "/NewRes/" + strName + fileSuffix;
}
else
{
path = streamingAssetsPath;
}
}
}
return path;
}
}