using UnityEngine;
using System.Collections;
using System.Collections.Generic;
namespace Engine.CLoader
{
/// 客户端加载对象处理器器
public class CLoaderManager : MonoBehaviour
{
#region 单利
private static CLoaderManager instance;
/// 单利对象
public static CLoaderManager GetInstance()
{
if (instance == null)
{
GameObject managerGO = new GameObject();
DontDestroyOnLoad(managerGO);
managerGO.name = "CLoaderManager";
instance = managerGO.AddComponent();
}
return instance;
}
#endregion
/// 缓存的loader对象列表
private List catchLoaderList = new List();
/// 当前缓存的资源
private List catchAssetsList = new List();
/// 现在中的loader个数
private int loadIngLoaderCount = 0;
/// 是否初始化了处理器
public bool IsInitManager = false;
/// 空构造函数
public CLoaderManager() { }
/// 初始化处理器
public void InitManager(CLoaderData configData)
{
//创建Loader对象
CreateCatchLoader();
//加载配置文件
this.LoadAssets(configData);
}
/// 预先创建加载对象
private void CreateCatchLoader()
{
for (int i = 0; i < CLoaderConst.CLoaderMaxCount; i++)
{
catchLoaderList.Add(new CLoaderAB());
}
}
/// 回收内存
public void GC()
{
//Resources.UnloadUnusedAssets ();
}
/// 添加资源
private void AddAssets(CLoaderAB loader)
{
CAssetsInfo assetsInfo = FindEmptyAssets();
if(assetsInfo==null)
{
assetsInfo = new CAssetsInfo();
catchAssetsList.Add(assetsInfo);
}
assetsInfo.assetsBundle = loader.assetsBundle;
assetsInfo.assetsName = loader.assetsName;
assetsInfo.isEmpty = false;
}
/// 查找获得名称的资源包数据
internal CAssetsInfo GetAssets(string assetsName)
{
CAssetsInfo assetsInfo = this.FindAssetsByAssetsName(assetsName);
if (assetsInfo != null)
{
assetsInfo.AddUseCount();
}
return assetsInfo;
}
/// 查找一个空的CAssetsInfo
private CAssetsInfo FindEmptyAssets()
{
for (int i = 0; i < catchAssetsList.Count; i++)
{
if(catchAssetsList[i].isEmpty)
{
return catchAssetsList[i];
}
}
return null;
}
/// 查找指定名称的资源
private CAssetsInfo FindAssetsByAssetsName(string assetsName)
{
for (int i = 0; i < catchAssetsList.Count; i++)
{
if (catchAssetsList[i].assetsName == assetsName)
{
return catchAssetsList[i];
}
}
return null;
}
/// 等待执行的loaderData,下载逻辑是两层队列,这是第一层队列
private List waitLoadDataList = new List();
/// 实际需要下载的资源
private List waitNeedLoadAssets = new List();
/// 加载资源
public void LoadAssets(CLoaderData loaderData)
{
//添加到队列
waitLoadDataList.Add(loaderData);
//执行一个LoadData
if (waitLoadDataList.Count == 1)
{
this.LoadFistLoaderData();
}
}
/// 加载第一个CLoaderData
private void LoadFistLoaderData()
{
if(waitLoadDataList.Count==0)
{ return; }
//获得数据
CLoaderData loaderData = waitLoadDataList[0];
//循环长度
int forLeng = 0;
//不是配置文件
if (loaderData.assetsType != AssetsType.Config)
{
//如果有依赖的包先下载依赖的包
List assetsConfigList = loaderData.AssetsConfigList;
forLeng = assetsConfigList.Count;
bool isDataComplete = false;
for (int i = 0; i < forLeng; i++)
{
if(LoadDepAssets(assetsConfigList[i], assetsConfigList[i]))
{
isDataComplete = true;
break;
}
}
if(isDataComplete)
{
OnFirstLoaderComplete();
}
}
//资源配置文件,这时还获取不到资源的配置数据
else
{
forLeng = loaderData.listAssetsName.Count;
for (int i = 0; i < forLeng; i++)
{
this.AddNeedLoadAssets(loaderData.listAssetsName[i]);
}
}
}
/// 递归次数,避免死循环不方便查找错误,如果递归超过20层,报错不在递归下去
private int recursiveCount = 0;
/// 下载依赖的包
private bool LoadDepAssets(CAssetsConfigInfo assetsConfigInfo, CAssetsConfigInfo debugInfo)
{
//增加递归次数
recursiveCount++;
//如果递归超过20层,报错不在递归下去
if(recursiveCount>20)
{
#if UNITY_EDITOR
CDebug.LogError("包的依赖关系层次超过20层 name=" + debugInfo.assetsName);
#endif
return false;
}
//依赖项依赖的资源 循环递归,如果存在循环依赖关系这里会死循环
if(assetsConfigInfo==null)
{
CDebug.Log("assetsConfigInfo==null");
return false;
}
int depCount = assetsConfigInfo.AssetsDepInfoList.Count;
for (int i = 0; i < depCount; i++)
{
//递归下载
LoadDepAssets(assetsConfigInfo.AssetsDepInfoList[i], debugInfo);
}
//添加到需要的下载的队列
bool isDataComplete = this.AddNeedLoadAssets(assetsConfigInfo.assetsName);
//减少递归次数
recursiveCount--;
return isDataComplete;
}
/// 添加需要下载的资源
private bool AddNeedLoadAssets(string needAssets)
{
//是否已经下载完毕
CAssetsInfo assetsInfo = this.GetAssets(needAssets);
if (assetsInfo!=null)
{
waitLoadDataList[0].UpdateProgress(assetsInfo.assetsName, 100);
return waitLoadDataList[0].ChectLoadComplete(assetsInfo);
}
//是否已经在队列中
if (waitNeedLoadAssets.IndexOf(needAssets)!=-1)
{
return false;
}
//是否在下载中
for (int i = 0; i < CLoaderConst.CLoaderMaxCount; i++)
{
if (!catchLoaderList[i].IsLoadIng)
{ continue; }
if(catchLoaderList[i].assetsName == needAssets)
{
return false;
}
}
//添加队列
waitNeedLoadAssets.Add(needAssets);
//检查是否有空闲的loader,如果有下载队列中的资源
if(waitNeedLoadAssets.Count==1)
{
this.CheckStartLoad();
}
return false;
}
/// 检查是否可以开始下载资源
private void CheckStartLoad()
{
//没有需要下载的资源了
if (waitNeedLoadAssets.Count == 0)
{
return;
}
string assetsName = "";
for (int i = 0; i < CLoaderConst.CLoaderMaxCount; i++)
{
if (catchLoaderList[i].IsLoadIng)
{ continue; }
//真正的开始下载 下载进度和是否下载完成全都在update函数中检查
assetsName = waitNeedLoadAssets[0];
waitNeedLoadAssets.RemoveAt(0);
loadIngLoaderCount++;
catchLoaderList[i].StartLoad(CLoaderConst.AssetsBundleURL + assetsName, assetsName);
//没有需要下载的资源了
if(waitNeedLoadAssets.Count==0)
{
break;
}
}
}
/// 帧频函数
private void Update()
{
//检查场景加载
CheckSceneAsync();
//没有资源在下载不需要检查
if(loadIngLoaderCount==0)
{ return; }
//整个的loaderdata是否下载完毕,第一层队列是否下载完毕
bool isDataComplete = false;
//第二层队列是否有loader下载完毕
bool isBeLoadComplete = false;
CLoaderData loaderData = waitLoadDataList[0];
CLoaderAB loader = null;
for (int i = 0; i < CLoaderConst.CLoaderMaxCount; i++)
{
loader = catchLoaderList[i];
if (!loader.IsLoadIng)
{ continue; }
loader.OnUpdate();
//下载完成
if(loader.IsLoadComplete)
{
//让资源入库
this.AddAssets(loader);
//检查DataLoader整体是否下载完毕
isDataComplete = loaderData.ChectLoadComplete(this.GetAssets(loader.assetsName));
//重置loader对象
loader.Reset();
//标记有loader空闲了
isBeLoadComplete = true;
//修改使用中的loader个数
loadIngLoaderCount--;
//资源下载完毕 跳出循环 执行回调和下一个LoaderData
if (isDataComplete)
{
break;
}
}
else
{
loaderData.UpdateProgress(loader.assetsName, loader.LoadProgress);
}
}
//执行回调和下一个LoaderData
if(isDataComplete)
{
OnFirstLoaderComplete();
}
//第二层队列是否有loader下载完毕
else if (isBeLoadComplete)
{
this.CheckStartLoad();
}
}
/// LoadData下载完毕
private void OnFirstLoaderComplete()
{
CLoaderData loaderData = waitLoadDataList[0];
//从队列中删除第一个资源
waitLoadDataList.RemoveAt(0);
//执行回调
loaderData.OnCompleteCallBack();
//继续下载
this.LoadFistLoaderData();
}
/// 场景加载对象
private AsyncOperation mSceneAsync = null;
/// 加载完成回调
private OnDelegateLoadSceneComplete OnLoadSceneComplete;
/// 当前场景名称
private string strCurSceneName = "";
/// 当前场景名称
public string CurSceneName
{
get { return strCurSceneName; }
}
private string strLoadingSceneName = "";
/// 加载场景
public void LoadScene(string sceneName, OnDelegateLoadSceneComplete onLoadSceneComplete)
{
//当前场景就是需要加载的场景
if (sceneName == strCurSceneName)
{
if (onLoadSceneComplete != null)
{
onLoadSceneComplete();
}
return;
}
//正在加载其他场景
if (mSceneAsync!=null)
{
CDebug.LogError("重复调用加载场景逻辑!");
return;
}
OnLoadSceneComplete = onLoadSceneComplete;
strLoadingSceneName = sceneName;
mSceneAsync = UnityEngine.SceneManagement.SceneManager.LoadSceneAsync (sceneName);
}
/// 检查异步加载场景是否完成
private void CheckSceneAsync()
{
//如果刚刚加载完成,等待一帧在返回true
if (mSceneAsync != null && mSceneAsync.isDone)
{
mSceneAsync = null;
strCurSceneName = strLoadingSceneName;
if (OnLoadSceneComplete != null)
{
OnDelegateLoadSceneComplete onCallBack = OnLoadSceneComplete;
OnLoadSceneComplete = null;
onCallBack();
onCallBack = null;
}
}
}
}
}