CLoaderManager.cs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412
  1. using UnityEngine;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. namespace Engine.CLoader
  5. {
  6. /// <summary>客户端加载对象处理器器</summary>
  7. public class CLoaderManager : MonoBehaviour
  8. {
  9. #region 单利
  10. private static CLoaderManager instance;
  11. /// <summary>单利对象</summary>
  12. public static CLoaderManager GetInstance()
  13. {
  14. if (instance == null)
  15. {
  16. GameObject managerGO = new GameObject();
  17. DontDestroyOnLoad(managerGO);
  18. managerGO.name = "CLoaderManager";
  19. instance = managerGO.AddComponent<CLoaderManager>();
  20. }
  21. return instance;
  22. }
  23. #endregion
  24. /// <summary>缓存的loader对象列表</summary>
  25. private List<CLoaderAB> catchLoaderList = new List<CLoaderAB>();
  26. /// <summary>当前缓存的资源</summary>
  27. private List<CAssetsInfo> catchAssetsList = new List<CAssetsInfo>();
  28. /// <summary>现在中的loader个数</summary>
  29. private int loadIngLoaderCount = 0;
  30. /// <summary>是否初始化了处理器</summary>
  31. public bool IsInitManager = false;
  32. /// <summary>空构造函数</summary>
  33. public CLoaderManager() { }
  34. /// <summary>初始化处理器</summary>
  35. public void InitManager(CLoaderData configData)
  36. {
  37. //创建Loader对象
  38. CreateCatchLoader();
  39. //加载配置文件
  40. this.LoadAssets(configData);
  41. }
  42. /// <summary>预先创建加载对象</summary>
  43. private void CreateCatchLoader()
  44. {
  45. for (int i = 0; i < CLoaderConst.CLoaderMaxCount; i++)
  46. {
  47. catchLoaderList.Add(new CLoaderAB());
  48. }
  49. }
  50. /// <summary>回收内存</summary>
  51. public void GC()
  52. {
  53. //Resources.UnloadUnusedAssets ();
  54. }
  55. /// <summary>添加资源</summary>
  56. private void AddAssets(CLoaderAB loader)
  57. {
  58. CAssetsInfo assetsInfo = FindEmptyAssets();
  59. if(assetsInfo==null)
  60. {
  61. assetsInfo = new CAssetsInfo();
  62. catchAssetsList.Add(assetsInfo);
  63. }
  64. assetsInfo.assetsBundle = loader.assetsBundle;
  65. assetsInfo.assetsName = loader.assetsName;
  66. assetsInfo.isEmpty = false;
  67. }
  68. /// <summary>查找获得名称的资源包数据</summary>
  69. internal CAssetsInfo GetAssets(string assetsName)
  70. {
  71. CAssetsInfo assetsInfo = this.FindAssetsByAssetsName(assetsName);
  72. if (assetsInfo != null)
  73. {
  74. assetsInfo.AddUseCount();
  75. }
  76. return assetsInfo;
  77. }
  78. /// <summary>查找一个空的CAssetsInfo</summary>
  79. private CAssetsInfo FindEmptyAssets()
  80. {
  81. for (int i = 0; i < catchAssetsList.Count; i++)
  82. {
  83. if(catchAssetsList[i].isEmpty)
  84. {
  85. return catchAssetsList[i];
  86. }
  87. }
  88. return null;
  89. }
  90. /// <summary>查找指定名称的资源</summary>
  91. private CAssetsInfo FindAssetsByAssetsName(string assetsName)
  92. {
  93. for (int i = 0; i < catchAssetsList.Count; i++)
  94. {
  95. if (catchAssetsList[i].assetsName == assetsName)
  96. {
  97. return catchAssetsList[i];
  98. }
  99. }
  100. return null;
  101. }
  102. /// <summary>等待执行的loaderData,下载逻辑是两层队列,这是第一层队列</summary>
  103. private List<CLoaderData> waitLoadDataList = new List<CLoaderData>();
  104. /// <summary>实际需要下载的资源</summary>
  105. private List<string> waitNeedLoadAssets = new List<string>();
  106. /// <summary>加载资源</summary>
  107. public void LoadAssets(CLoaderData loaderData)
  108. {
  109. //添加到队列
  110. waitLoadDataList.Add(loaderData);
  111. //执行一个LoadData
  112. if (waitLoadDataList.Count == 1)
  113. {
  114. this.LoadFistLoaderData();
  115. }
  116. }
  117. /// <summary>加载第一个CLoaderData</summary>
  118. private void LoadFistLoaderData()
  119. {
  120. if(waitLoadDataList.Count==0)
  121. { return; }
  122. //获得数据
  123. CLoaderData loaderData = waitLoadDataList[0];
  124. //循环长度
  125. int forLeng = 0;
  126. //不是配置文件
  127. if (loaderData.assetsType != AssetsType.Config)
  128. {
  129. //如果有依赖的包先下载依赖的包
  130. List<CAssetsConfigInfo> assetsConfigList = loaderData.AssetsConfigList;
  131. forLeng = assetsConfigList.Count;
  132. bool isDataComplete = false;
  133. for (int i = 0; i < forLeng; i++)
  134. {
  135. if(LoadDepAssets(assetsConfigList[i], assetsConfigList[i]))
  136. {
  137. isDataComplete = true;
  138. break;
  139. }
  140. }
  141. if(isDataComplete)
  142. {
  143. OnFirstLoaderComplete();
  144. }
  145. }
  146. //资源配置文件,这时还获取不到资源的配置数据
  147. else
  148. {
  149. forLeng = loaderData.listAssetsName.Count;
  150. for (int i = 0; i < forLeng; i++)
  151. {
  152. this.AddNeedLoadAssets(loaderData.listAssetsName[i]);
  153. }
  154. }
  155. }
  156. /// <summary>递归次数,避免死循环不方便查找错误,如果递归超过20层,报错不在递归下去</summary>
  157. private int recursiveCount = 0;
  158. /// <summary>下载依赖的包</summary>
  159. private bool LoadDepAssets(CAssetsConfigInfo assetsConfigInfo, CAssetsConfigInfo debugInfo)
  160. {
  161. //增加递归次数
  162. recursiveCount++;
  163. //如果递归超过20层,报错不在递归下去
  164. if(recursiveCount>20)
  165. {
  166. #if UNITY_EDITOR
  167. CDebug.LogError("包的依赖关系层次超过20层 name=" + debugInfo.assetsName);
  168. #endif
  169. return false;
  170. }
  171. //依赖项依赖的资源 循环递归,如果存在循环依赖关系这里会死循环
  172. if(assetsConfigInfo==null)
  173. {
  174. CDebug.Log("assetsConfigInfo==null");
  175. return false;
  176. }
  177. int depCount = assetsConfigInfo.AssetsDepInfoList.Count;
  178. for (int i = 0; i < depCount; i++)
  179. {
  180. //递归下载
  181. LoadDepAssets(assetsConfigInfo.AssetsDepInfoList[i], debugInfo);
  182. }
  183. //添加到需要的下载的队列
  184. bool isDataComplete = this.AddNeedLoadAssets(assetsConfigInfo.assetsName);
  185. //减少递归次数
  186. recursiveCount--;
  187. return isDataComplete;
  188. }
  189. /// <summary>添加需要下载的资源</summary>
  190. private bool AddNeedLoadAssets(string needAssets)
  191. {
  192. //是否已经下载完毕
  193. CAssetsInfo assetsInfo = this.GetAssets(needAssets);
  194. if (assetsInfo!=null)
  195. {
  196. waitLoadDataList[0].UpdateProgress(assetsInfo.assetsName, 100);
  197. return waitLoadDataList[0].ChectLoadComplete(assetsInfo);
  198. }
  199. //是否已经在队列中
  200. if (waitNeedLoadAssets.IndexOf(needAssets)!=-1)
  201. {
  202. return false;
  203. }
  204. //是否在下载中
  205. for (int i = 0; i < CLoaderConst.CLoaderMaxCount; i++)
  206. {
  207. if (!catchLoaderList[i].IsLoadIng)
  208. { continue; }
  209. if(catchLoaderList[i].assetsName == needAssets)
  210. {
  211. return false;
  212. }
  213. }
  214. //添加队列
  215. waitNeedLoadAssets.Add(needAssets);
  216. //检查是否有空闲的loader,如果有下载队列中的资源
  217. if(waitNeedLoadAssets.Count==1)
  218. {
  219. this.CheckStartLoad();
  220. }
  221. return false;
  222. }
  223. /// <summary>检查是否可以开始下载资源</summary>
  224. private void CheckStartLoad()
  225. {
  226. //没有需要下载的资源了
  227. if (waitNeedLoadAssets.Count == 0)
  228. {
  229. return;
  230. }
  231. string assetsName = "";
  232. for (int i = 0; i < CLoaderConst.CLoaderMaxCount; i++)
  233. {
  234. if (catchLoaderList[i].IsLoadIng)
  235. { continue; }
  236. //真正的开始下载 下载进度和是否下载完成全都在update函数中检查
  237. assetsName = waitNeedLoadAssets[0];
  238. waitNeedLoadAssets.RemoveAt(0);
  239. loadIngLoaderCount++;
  240. catchLoaderList[i].StartLoad(CLoaderConst.AssetsBundleURL + assetsName, assetsName);
  241. //没有需要下载的资源了
  242. if(waitNeedLoadAssets.Count==0)
  243. {
  244. break;
  245. }
  246. }
  247. }
  248. /// <summary>帧频函数</summary>
  249. private void Update()
  250. {
  251. //检查场景加载
  252. CheckSceneAsync();
  253. //没有资源在下载不需要检查
  254. if(loadIngLoaderCount==0)
  255. { return; }
  256. //整个的loaderdata是否下载完毕,第一层队列是否下载完毕
  257. bool isDataComplete = false;
  258. //第二层队列是否有loader下载完毕
  259. bool isBeLoadComplete = false;
  260. CLoaderData loaderData = waitLoadDataList[0];
  261. CLoaderAB loader = null;
  262. for (int i = 0; i < CLoaderConst.CLoaderMaxCount; i++)
  263. {
  264. loader = catchLoaderList[i];
  265. if (!loader.IsLoadIng)
  266. { continue; }
  267. loader.OnUpdate();
  268. //下载完成
  269. if(loader.IsLoadComplete)
  270. {
  271. //让资源入库
  272. this.AddAssets(loader);
  273. //检查DataLoader整体是否下载完毕
  274. isDataComplete = loaderData.ChectLoadComplete(this.GetAssets(loader.assetsName));
  275. //重置loader对象
  276. loader.Reset();
  277. //标记有loader空闲了
  278. isBeLoadComplete = true;
  279. //修改使用中的loader个数
  280. loadIngLoaderCount--;
  281. //资源下载完毕 跳出循环 执行回调和下一个LoaderData
  282. if (isDataComplete)
  283. {
  284. break;
  285. }
  286. }
  287. else
  288. {
  289. loaderData.UpdateProgress(loader.assetsName, loader.LoadProgress);
  290. }
  291. }
  292. //执行回调和下一个LoaderData
  293. if(isDataComplete)
  294. {
  295. OnFirstLoaderComplete();
  296. }
  297. //第二层队列是否有loader下载完毕
  298. else if (isBeLoadComplete)
  299. {
  300. this.CheckStartLoad();
  301. }
  302. }
  303. /// <summary>LoadData下载完毕</summary>
  304. private void OnFirstLoaderComplete()
  305. {
  306. CLoaderData loaderData = waitLoadDataList[0];
  307. //从队列中删除第一个资源
  308. waitLoadDataList.RemoveAt(0);
  309. //执行回调
  310. loaderData.OnCompleteCallBack();
  311. //继续下载
  312. this.LoadFistLoaderData();
  313. }
  314. /// <summary>场景加载对象</summary>
  315. private AsyncOperation mSceneAsync = null;
  316. /// <summary>加载完成回调</summary>
  317. private OnDelegateLoadSceneComplete OnLoadSceneComplete;
  318. /// <summary>当前场景名称</summary>
  319. private string strCurSceneName = "";
  320. /// <summary>当前场景名称</summary>
  321. public string CurSceneName
  322. {
  323. get { return strCurSceneName; }
  324. }
  325. private string strLoadingSceneName = "";
  326. /// <summary>加载场景</summary>
  327. public void LoadScene(string sceneName, OnDelegateLoadSceneComplete onLoadSceneComplete)
  328. {
  329. //当前场景就是需要加载的场景
  330. if (sceneName == strCurSceneName)
  331. {
  332. if (onLoadSceneComplete != null)
  333. {
  334. onLoadSceneComplete();
  335. }
  336. return;
  337. }
  338. //正在加载其他场景
  339. if (mSceneAsync!=null)
  340. {
  341. CDebug.LogError("重复调用加载场景逻辑!");
  342. return;
  343. }
  344. OnLoadSceneComplete = onLoadSceneComplete;
  345. strLoadingSceneName = sceneName;
  346. mSceneAsync = UnityEngine.SceneManagement.SceneManager.LoadSceneAsync (sceneName);
  347. }
  348. /// <summary>检查异步加载场景是否完成</summary>
  349. private void CheckSceneAsync()
  350. {
  351. //如果刚刚加载完成,等待一帧在返回true
  352. if (mSceneAsync != null && mSceneAsync.isDone)
  353. {
  354. mSceneAsync = null;
  355. strCurSceneName = strLoadingSceneName;
  356. if (OnLoadSceneComplete != null)
  357. {
  358. OnDelegateLoadSceneComplete onCallBack = OnLoadSceneComplete;
  359. OnLoadSceneComplete = null;
  360. onCallBack();
  361. onCallBack = null;
  362. }
  363. }
  364. }
  365. }
  366. }