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; } } } } }