Unity 框架

ResourceManager.cs 18KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using UnityEngine;
  5. using UnityEngine.SceneManagement;
  6. namespace TFramework
  7. {
  8. public class ResourceManager : BaseManager
  9. {
  10. /// <summary>
  11. /// 所有AssetBundle资源包清单
  12. /// </summary>
  13. public AssetBundleManifest AssetBundleManifest { get; private set; }
  14. /// <summary>
  15. /// 缓存的所有AssetBundle包【AB包名称、AB包】
  16. /// </summary>
  17. public Dictionary<string, AssetBundle> AssetBundles { get; private set; } = new Dictionary<string, AssetBundle>();
  18. /// <summary>
  19. /// 当前激活的场景
  20. /// </summary>
  21. public Scene CurrentScene { get; private set; }
  22. public void Awake()
  23. {
  24. CurrentScene= SceneManager.GetActiveScene();
  25. }
  26. public T LoadAsset<T>(LoadResHandle<T> resHandle) where T : UnityEngine.Object
  27. {
  28. return LoadAsset<T>(resHandle.ResourcePath, resHandle.AssetPath, resHandle.AssetBundleName, resHandle.LoadMode);
  29. }
  30. /// <summary>
  31. /// 同步加载资源
  32. /// </summary>
  33. /// <typeparam name="T"></typeparam>
  34. /// <param name="resPath"></param>
  35. /// <param name="assetPath"></param>
  36. /// <param name="assetBundleName"></param>
  37. /// <param name="resLoadMode"></param>
  38. /// <returns></returns>
  39. public T LoadAsset<T>(string resPath, string assetPath, string assetBundleName = "", ResLoadMode resLoadMode = ResLoadMode.Resourece) where T : UnityEngine.Object
  40. {
  41. if (resLoadMode == ResLoadMode.Resourece)
  42. return Resources.Load<T>(resPath);
  43. else
  44. {
  45. #if UNITY_EDITOR
  46. if (AssetConfig.RuntimeMode == UpdateMode.Editor)
  47. return UnityEditor.AssetDatabase.LoadAssetAtPath<T>(assetPath);
  48. #endif
  49. if (AssetBundleManifest == null)
  50. {
  51. if (!AssetBundles.ContainsKey(AssetConfig.AssetBundleManifestName))
  52. AssetBundles.Add(AssetConfig.AssetBundleManifestName,
  53. AssetBundle.LoadFromFile(AssetConfig.AssetBundleRootPath + AssetConfig.AssetBundleManifestName));
  54. AssetBundleManifest = AssetBundles[AssetConfig.AssetBundleManifestName].LoadAsset<AssetBundleManifest>("AssetBundleManifest");
  55. }
  56. string[] dependencies = AssetBundleManifest.GetAllDependencies(assetBundleName);
  57. for (int i = 0; i < dependencies.Length; i++)
  58. {
  59. if (!AssetBundles.ContainsKey(dependencies[i]))
  60. AssetBundles.Add(dependencies[i], AssetBundle.LoadFromFile(AssetConfig.AssetBundleRootPath + dependencies[i]));
  61. }
  62. if (!AssetBundles.ContainsKey(assetBundleName))
  63. AssetBundles.Add(assetBundleName, AssetBundle.LoadFromFile(AssetConfig.AssetBundleRootPath + assetBundleName));
  64. return AssetBundles[assetBundleName].LoadAsset<T>(assetPath);
  65. }
  66. }
  67. /// <summary>
  68. /// 同步加载Resources下的资源
  69. /// </summary>
  70. /// <typeparam name="T">资源类型</typeparam>
  71. /// <param name="resPath">资源路径</param>
  72. /// <returns></returns>
  73. public T LoadAsset<T>(string resPath) where T : UnityEngine.Object => LoadAsset<T>(resPath, "", "");
  74. /// <summary>
  75. /// 同步加载AssetBundle资源
  76. /// </summary>
  77. /// <typeparam name="T">资源类型</typeparam>
  78. /// <param name="assetPath">资源路径</param>
  79. /// <param name="assetBundleName">AB包名</param>
  80. /// <returns></returns>
  81. public T LoadAsset<T>(string assetPath, string assetBundleName) where T : UnityEngine.Object => LoadAsset<T>("", assetPath, assetBundleName, ResLoadMode.AssetBundle);
  82. /// <summary>
  83. /// 异步加载资源
  84. /// </summary>
  85. /// <typeparam name="T">资源类型</typeparam>
  86. /// <param name="resPath">资源路径</param>
  87. /// <param name="onLoading">加载中事件</param>
  88. /// <param name="onLoadDone">加载完成事件</param>
  89. /// <returns></returns>
  90. public Coroutine LoadAssetAsync<T>(LoadResHandle<T> resHandle) where T : UnityEngine.Object
  91. {
  92. return StartCoroutine(LoadAsync(resHandle));
  93. }
  94. private IEnumerator LoadAsync<T>(LoadResHandle<T> resHandle) where T : UnityEngine.Object
  95. {
  96. UnityEngine.Object asset = null;
  97. if (resHandle.LoadMode == ResLoadMode.Resourece)
  98. {
  99. ResourceRequest request = Resources.LoadAsync<T>(resHandle.ResourcePath);
  100. while (!request.isDone)
  101. {
  102. resHandle.OnLoading?.Invoke(request.progress);
  103. yield return null;
  104. }
  105. resHandle.OnLoading?.Invoke(1);
  106. if (!request.asset)
  107. throw new UnityException($"资源加载失败:Resources文件夹中不存在资源 {resHandle.ResourcePath}!");
  108. else
  109. asset = request.asset;
  110. }
  111. else
  112. {
  113. #if UNITY_EDITOR
  114. if (AssetConfig.RuntimeMode == UpdateMode.Editor)
  115. {
  116. resHandle.OnLoading?.Invoke(1);
  117. asset = UnityEditor.AssetDatabase.LoadAssetAtPath<T>(resHandle.AssetPath);
  118. if (asset)
  119. asset = asset as T;
  120. else
  121. throw new UnityException($"加载资源失败:路径{resHandle.AssetPath}中不存在资源 {resHandle.AssetPath}!");
  122. }
  123. else
  124. {
  125. //等待相关依赖资源的加载
  126. yield return LoadDependenciesAssetBundleAsync(resHandle.AssetBundleName);
  127. yield return LoadAssetBundleAsync(resHandle.AssetBundleName, resHandle.OnLoading);
  128. if (AssetBundles.ContainsKey(resHandle.AssetBundleName.ToLower()))
  129. {
  130. //asset = AssetBundles[resHandle.AssetBundleName].LoadAsset<T>(resHandle.AssetPath);
  131. AssetBundleRequest request = AssetBundles[resHandle.AssetBundleName.ToLower()].LoadAssetAsync<T>(resHandle.AssetPath);
  132. yield return request;
  133. while (!request.isDone)
  134. {
  135. resHandle.OnLoading(request.progress / 2 + 0.5f);
  136. yield return null;
  137. }
  138. asset = request.asset;
  139. if (!asset)
  140. throw new UnityException(string.Format("加载资源失败:AB包 {0} 中不存在资源 {1}!", resHandle.AssetBundleName, resHandle.AssetPath));
  141. }
  142. }
  143. #else
  144. yield return LoadDependenciesAssetBundleAsync(resHandle.AssetBundleName);
  145. yield return LoadAssetBundleAsync(resHandle.AssetBundleName, resHandle.OnLoading);
  146. if (AssetBundles.ContainsKey(resHandle.AssetBundleName.ToLower()))
  147. {
  148. AssetBundleRequest request = AssetBundles[resHandle.AssetBundleName.ToLower()].LoadAssetAsync<T>(resHandle.AssetPath);
  149. yield return request;
  150. while(!request.isDone)
  151. {
  152. resHandle.OnLoading(request.progress / 2+0.5f);
  153. yield return null;
  154. }
  155. asset = request.asset;
  156. if (!asset)
  157. throw new UnityException(string.Format("加载资源失败:AB包 {0} 中不存在资源 {1}!", resHandle.AssetBundleName, resHandle.AssetPath));
  158. }
  159. #endif
  160. }
  161. if (asset)
  162. {
  163. resHandle.OnLoadOver?.Invoke(asset as T);
  164. }
  165. else
  166. resHandle.OnLoadOver?.Invoke(null);
  167. }
  168. /// <summary>
  169. /// 异步加载场景(Resource模式)
  170. /// </summary>
  171. /// <param name="scenePath">场景路径</param>
  172. /// <param name="onLoading">加载中事件</param>
  173. /// <param name="onLoadDone">加载完成事件</param>
  174. /// <returns></returns>
  175. public Coroutine LoadSceneAsync(string scenePath, TAction<float> OnLoading, TAction<Scene> OnLoadOver, LoadSceneMode loadSceneMode = LoadSceneMode.Single)
  176. {
  177. return StartCoroutine(LoadScene(scenePath, ResLoadMode.Resourece, "", OnLoading, OnLoadOver, loadSceneMode));
  178. }
  179. /// <summary>
  180. /// 异步加载场景
  181. /// </summary>
  182. /// <param name="scenePath">场景路径</param>
  183. /// <param name="onLoading">加载中事件</param>
  184. /// <param name="onLoadDone">加载完成事件</param>
  185. /// <returns></returns>
  186. public Coroutine LoadSceneAsync(LoadResHandle<Scene> resHandle, LoadSceneMode loadSceneMode = LoadSceneMode.Single)
  187. {
  188. return StartCoroutine(LoadScene(resHandle.AssetPath,resHandle.LoadMode,resHandle.AssetBundleName,resHandle.OnLoading,resHandle.OnLoadOver, loadSceneMode));
  189. }
  190. private IEnumerator LoadScene(string scenePath, ResLoadMode loadMode ,string assetBundleName ,TAction<float> OnLoading,TAction<Scene> OnLoadOver, LoadSceneMode loadSceneMode)
  191. {
  192. if (SceneManager.GetSceneByPath(scenePath) == CurrentScene)
  193. {
  194. Debug.LogWarning($"场景{scenePath}已加载!");
  195. yield break;
  196. }
  197. if (loadMode == ResLoadMode.Resourece)
  198. {
  199. AsyncOperation ao = SceneManager.LoadSceneAsync(scenePath, loadSceneMode);
  200. while (!ao.isDone)
  201. {
  202. OnLoading?.Invoke(ao.progress);
  203. yield return null;
  204. }
  205. }
  206. else
  207. {
  208. yield return LoadDependenciesAssetBundleAsync(assetBundleName);
  209. #if UNITY_EDITOR
  210. if (AssetConfig.RuntimeMode == UpdateMode.Editor)
  211. {
  212. LoadSceneParameters parameters = new LoadSceneParameters()
  213. {
  214. loadSceneMode = LoadSceneMode.Single,
  215. localPhysicsMode = LocalPhysicsMode.None
  216. };
  217. AsyncOperation ao = UnityEditor.SceneManagement.EditorSceneManager.LoadSceneAsyncInPlayMode(scenePath, parameters);
  218. while (!ao.isDone)
  219. {
  220. OnLoading?.Invoke(ao.progress);
  221. yield return null;
  222. }
  223. }
  224. else
  225. {
  226. yield return LoadAssetBundleAsync(assetBundleName, OnLoading);
  227. AsyncOperation ao = SceneManager.LoadSceneAsync(scenePath, loadSceneMode);
  228. while (!ao.isDone)
  229. {
  230. OnLoading?.Invoke(ao.progress);
  231. yield return null;
  232. }
  233. }
  234. #else
  235. yield return LoadAssetBundleAsync(assetBundleName, OnLoading);
  236. AsyncOperation ao = SceneManager.LoadSceneAsync(scenePath, loadSceneMode);
  237. while (!ao.isDone)
  238. {
  239. OnLoading?.Invoke(ao.progress);
  240. yield return null;
  241. }
  242. #endif
  243. }
  244. OnLoading?.Invoke(1);
  245. OnLoadOver?.Invoke(SceneManager.GetSceneByPath(scenePath));
  246. CurrentScene = SceneManager.GetActiveScene();
  247. //SceneManager.SetActiveScene(CurrentScene);
  248. }
  249. /// <summary>
  250. /// 异步清理内存 回收垃圾
  251. /// </summary>
  252. /// <returns></returns>
  253. public Coroutine ClearMemoryAsync()
  254. {
  255. return StartCoroutine(ClearMemory());
  256. }
  257. /// <summary>
  258. /// 清理内存,释放空闲内存(异步)
  259. /// </summary>
  260. /// <returns>协程迭代器</returns>
  261. private IEnumerator ClearMemory()
  262. {
  263. yield return Resources.UnloadUnusedAssets();
  264. GC.Collect();
  265. GC.WaitForPendingFinalizers();
  266. }
  267. /// <summary>
  268. /// 异步卸载资源
  269. /// </summary>
  270. /// <returns></returns>
  271. public Coroutine UnLoadAsstAsync(ResLoadMode resLoadMode, string assetBundleName, bool unloadAllLoadedObjects = false)
  272. {
  273. return StartCoroutine(UnLoadAsst(resLoadMode, assetBundleName, unloadAllLoadedObjects));
  274. }
  275. private IEnumerator UnLoadAsst(ResLoadMode resLoadMode, string assetBundleName, bool unloadAllLoadedObjects = false)
  276. {
  277. yield return UnLoadAsset(ResLoadMode.Resourece, assetBundleName, unloadAllLoadedObjects);
  278. }
  279. /// <summary>
  280. /// 异步卸载场景
  281. /// </summary>
  282. /// <param name="scene"></param>
  283. /// <returns></returns>
  284. public Coroutine UnloadSceneAsync(Scene scene, TAction<float> OnUnloading = null, TAction OnUnloadOver = null)
  285. {
  286. return StartCoroutine(UnloadScene(scene, OnUnloading, OnUnloadOver));
  287. }
  288. private IEnumerator UnloadScene(Scene scene, TAction<float> OnUnloading, TAction OnUnloadOver)
  289. {
  290. AsyncOperation ao = SceneManager.UnloadSceneAsync(scene);
  291. while (!ao.isDone)
  292. {
  293. OnUnloading?.Invoke(ao.progress);
  294. yield return null;
  295. }
  296. OnUnloadOver?.Invoke();
  297. CurrentScene = SceneManager.GetActiveScene();
  298. }
  299. public IEnumerator UnLoadAsset(ResLoadMode resLoadMode, string assetBundleName, bool unloadAllLoadedObjects = false)
  300. {
  301. if (resLoadMode == ResLoadMode.Resourece)
  302. {
  303. yield return Resources.UnloadUnusedAssets();
  304. }
  305. else
  306. {
  307. if (AssetBundles.ContainsKey(assetBundleName))
  308. {
  309. AssetBundles[assetBundleName].Unload(unloadAllLoadedObjects);
  310. AssetBundles.Remove(assetBundleName);
  311. }
  312. yield return null;
  313. }
  314. }
  315. /// <summary>
  316. /// 异步加载AB包清单
  317. /// </summary>
  318. /// <returns>协程迭代器</returns>
  319. private IEnumerator LoadAssetBundleManifestAsync()
  320. {
  321. if (string.IsNullOrEmpty(AssetConfig.AssetBundleManifestName))
  322. {
  323. throw new UnityException("请设置资源配置文件的 AssetBundleManifestName 属性,为所有AB包提供依赖清单!");
  324. }
  325. else
  326. {
  327. if (AssetBundleManifest == null)
  328. {
  329. yield return LoadAssetBundleAsync(AssetConfig.AssetBundleManifestName, null);
  330. if (AssetBundles.ContainsKey(AssetConfig.AssetBundleManifestName))
  331. {
  332. AssetBundleManifest = AssetBundles[AssetConfig.AssetBundleManifestName].LoadAsset<AssetBundleManifest>("AssetBundleManifest");
  333. UnLoadAsset(ResLoadMode.AssetBundle, AssetConfig.AssetBundleManifestName);
  334. }
  335. }
  336. }
  337. yield return null;
  338. }
  339. /// <summary>
  340. /// 异步加载AB包(提供进度回调)
  341. /// </summary>
  342. /// <param name="assetBundleName">AB包名称</param>
  343. /// <param name="onLoading">加载中事件</param>
  344. /// <param name="isManifest">是否是加载清单</param>
  345. /// <returns>协程迭代器</returns>
  346. private IEnumerator LoadAssetBundleAsync(string assetBundleName, TAction<float> onLoading)
  347. {
  348. assetBundleName = assetBundleName.ToLower();
  349. if (!AssetBundles.ContainsKey(assetBundleName))
  350. {
  351. AssetBundleCreateRequest abRequst = AssetBundle.LoadFromFileAsync(AssetConfig.AssetBundleRootPath + assetBundleName);
  352. yield return abRequst;
  353. while (!abRequst.isDone)
  354. {
  355. onLoading?.Invoke(abRequst.progress / 2);
  356. yield return null;
  357. }
  358. if (abRequst.assetBundle)
  359. AssetBundles.Add(assetBundleName, abRequst.assetBundle);
  360. else
  361. throw new UnityException($" 未加载到AB包【{assetBundleName}】!");
  362. }
  363. onLoading?.Invoke(1);
  364. }
  365. /// <summary>
  366. /// 异步加载依赖AB包
  367. /// </summary>
  368. /// <param name="assetBundleName">AB包名称</param>
  369. /// <returns>协程迭代器</returns>
  370. private IEnumerator LoadDependenciesAssetBundleAsync(string assetBundleName)
  371. {
  372. #if UNITY_EDITOR
  373. if (AssetConfig.RuntimeMode != UpdateMode.Editor)
  374. {
  375. yield return LoadAssetBundleManifestAsync();
  376. if (AssetBundleManifest != null)
  377. {
  378. string[] dependencies = AssetBundleManifest.GetAllDependencies(assetBundleName);
  379. foreach (string item in dependencies)
  380. {
  381. if (AssetBundles.ContainsKey(item))
  382. continue;
  383. yield return LoadAssetBundleAsync(item, null);
  384. }
  385. }
  386. }
  387. #else
  388. yield return LoadAssetBundleManifestAsync();
  389. if (AssetBundleManifest != null)
  390. {
  391. string[] dependencies = AssetBundleManifest.GetAllDependencies(assetBundleName);
  392. foreach (string item in dependencies)
  393. {
  394. if (AssetBundles.ContainsKey(item))
  395. {
  396. continue;
  397. }
  398. yield return LoadAssetBundleAsync(item,null);
  399. }
  400. }
  401. #endif
  402. yield return null;
  403. }
  404. }
  405. }