AssetManager.cs 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  1. using XGame.Framework.i18n;
  2. using System;
  3. using System.Collections.Generic;
  4. using XGame.Framework.Quality;
  5. using XGame.Framework.Asyncs;
  6. namespace XGame.Framework.Asset
  7. {
  8. public sealed partial class AssetManager : IAssetManager, IAsyncListener, IAssetCacheHandle
  9. {
  10. private enum OperateState : byte
  11. {
  12. None = 0,
  13. Prepare,
  14. Start,
  15. //End,
  16. }
  17. AssetRepository Repository { set; get; }
  18. Dictionary<string, IAssetAsync> AssetAsyncMap { set; get; }
  19. private List<IAsync> LoadingAsyncs { set; get; }
  20. IAssetLoader Loader { set; get; }
  21. IAddressableHandle AddressableHandler { set; get; }
  22. private LanguageType _languageType;
  23. private XQualityLevel _quality;
  24. private IAsync _disposeAsync;
  25. private bool _isDispose;
  26. private OperateState _unloadunusedOp;
  27. internal AssetManager(IAssetLoader loader)
  28. {
  29. Repository = new AssetRepository();
  30. AssetAsyncMap = new Dictionary<string, IAssetAsync>();
  31. LoadingAsyncs = new List<IAsync>();
  32. //AsyncPool = new AssetAsyncPool(new AssetAsyncAgentBuilder());
  33. //AsyncPool.AgentLimit = 10;
  34. Loader = loader;
  35. AddressableHandler = Loader as IAddressableHandle;
  36. _isDispose = false;
  37. _unloadunusedOp = OperateState.None;
  38. }
  39. TResult IAssetManager.LoadSync<TResult>(string addressableName)
  40. {
  41. if (_isDispose) return default;
  42. addressableName = AddressableHandler.ConvertAddressableName(new ConvertOptions(){
  43. addressableName = addressableName,
  44. quality = _quality,
  45. langType = _languageType
  46. }); //addressableName?.ToLower();
  47. var result = Repository.Clone(addressableName);
  48. if (result != null)
  49. {
  50. return result.Convert<TResult>(addressableName);
  51. }
  52. result = Loader.LoadSync<TResult>(addressableName);
  53. if (result != null)
  54. {
  55. var asset = AssetCreator.Create(addressableName, result);
  56. Repository.AddAsset(asset);
  57. result = Repository.Clone(addressableName);
  58. return result.Convert<TResult>(addressableName);
  59. }
  60. return default;
  61. }
  62. IAssetLoadAsync<TResult> IAssetManager.LoadAsync<TResult>(string addressableName)
  63. {
  64. if (_isDispose) return default;
  65. addressableName = AddressableHandler.ConvertAddressableName(new ConvertOptions()
  66. {
  67. addressableName = addressableName,
  68. quality = _quality,
  69. langType = _languageType
  70. }); //addressableName?.ToLower();
  71. IAssetAsync assetAsync = null;
  72. if (!Repository.ContainsAsset(addressableName))
  73. { //仓库中没找到资源
  74. //先取未完成的async
  75. if (!AssetAsyncMap.TryGetValue(addressableName, out assetAsync))
  76. {
  77. assetAsync = Loader.LoadAsync<TResult>(addressableName);//未加载
  78. if (assetAsync != null)
  79. {
  80. AssetAsyncMap.Add(assetAsync.AddressableName, assetAsync);
  81. assetAsync.On(OnAssetAsyncCompleted);
  82. //这里多做一个监听,且order要保证该监听在Async的最后执行
  83. assetAsync.On(this, int.MaxValue);
  84. }
  85. }
  86. }
  87. //
  88. var loadAsync = new AssetLoadAsync<TResult>(addressableName, assetAsync, this);
  89. LoadingAsyncs.Add(loadAsync);
  90. return loadAsync;
  91. }
  92. void IAssetManager.Recycle(object obj)
  93. {
  94. Repository.Recycle(obj);
  95. }
  96. void IAssetManager.StopAsync<TResult>(IAssetLoadAsync<TResult> async)
  97. {
  98. //这里只能停止业务的监听事件,不能停止AssetAsync的事件
  99. async.RemoveAll();
  100. //((AssetResultAsync<TResult>)async).StopAsync();
  101. }
  102. void IAssetManager.UnloadUnusedAssets()
  103. {
  104. if (_unloadunusedOp != OperateState.None)
  105. return;
  106. if (AssetAsyncMap.Count <= 0)
  107. {
  108. InnerUnloadUnusedAssets();
  109. }
  110. else
  111. {
  112. _unloadunusedOp = OperateState.Prepare;
  113. }
  114. }
  115. IAsync IAssetManager.LoadSceneBundle(string sceneName)
  116. {
  117. if (_isDispose || string.IsNullOrEmpty(sceneName)) return default;
  118. sceneName = sceneName.ToLower();
  119. IAssetAsync bundleAsync = null;
  120. if (!Repository.ContainsAsset(sceneName))
  121. { //仓库中没找到资源
  122. //先取未完成的async
  123. if (!AssetAsyncMap.TryGetValue(sceneName, out bundleAsync))
  124. {
  125. bundleAsync = Loader.LoadSceneBundleAsync(sceneName);//未加载
  126. if (bundleAsync != null)
  127. {
  128. AssetAsyncMap.Add(bundleAsync.AddressableName, bundleAsync);
  129. bundleAsync.On(OnAssetAsyncCompleted);
  130. //这里多做一个监听,且order要保证该监听在Async的最后执行
  131. bundleAsync.On(this, int.MaxValue);
  132. }
  133. }
  134. }
  135. return bundleAsync;
  136. }
  137. void IAssetManager.UnLoadSceneBundle(string sceneName)
  138. {
  139. Loader.UnLoadSceneBundle(sceneName);
  140. }
  141. private void InnerUnloadUnusedAssets()
  142. {
  143. _unloadunusedOp = OperateState.Start;
  144. Repository.UnloadUnusedAssets(((assetPath, source) =>
  145. {
  146. Loader.Unload(assetPath, source);
  147. }));
  148. Loader.UnloadUnusedAssets();
  149. _unloadunusedOp = OperateState.None;
  150. }
  151. //void IDisposable.Dispose()
  152. //{
  153. // //AsyncPool.Dispose();
  154. // Repository.Dispose();
  155. // (Loader as IDisposable)?.Dispose();
  156. // Loader = null;
  157. // AssetAsyncMap.Clear();
  158. //}
  159. IAsync IAssetManager.Dispose()
  160. {
  161. var async = new ManagerDisposeAsync();
  162. _isDispose = true;
  163. if (AssetAsyncMap.Count == 0)
  164. {
  165. InnerDispose();
  166. async.Completed();
  167. return async;
  168. }
  169. _disposeAsync = async;
  170. return _disposeAsync;
  171. }
  172. private void InnerDispose()
  173. {
  174. Repository.Dispose();
  175. (Loader as IDisposable)?.Dispose();
  176. Loader = null;
  177. AddressableHandler = null;
  178. AssetAsyncMap.Clear();
  179. for(var i = LoadingAsyncs.Count - 1; i >= 0; i--)
  180. {
  181. LoadingAsyncs[i].RemoveAll();
  182. }
  183. LoadingAsyncs.Clear();
  184. _disposeAsync = null;
  185. Monitor.AssetsMonitor.Dispose();
  186. }
  187. private void SetLangueType(LanguageType langType)
  188. {
  189. _languageType = langType;
  190. }
  191. private void SetQuality(XQualityLevel quality)
  192. {
  193. _quality = quality;
  194. }
  195. /// <summary>
  196. /// 转换AddressableName
  197. /// 会根据游戏当前语言、品质等级返回对应的AddressableName
  198. /// </summary>
  199. /// <param name="addressableName"></param>
  200. /// <returns></returns>
  201. string IAssetManager.ConvertAddressableName(string addressableName)
  202. {
  203. return AddressableHandler?.ConvertAddressableName(new ConvertOptions()
  204. {
  205. addressableName = addressableName,
  206. quality = _quality,
  207. langType = _languageType,
  208. }) ?? addressableName;
  209. }
  210. object IAssetCacheHandle.GetAssetFromCache(string addressableName)
  211. {
  212. return Repository.Clone(addressableName);
  213. }
  214. void IAssetCacheHandle.ReleaseAsync(IAsync async)
  215. {
  216. LoadingAsyncs.Remove(async);
  217. }
  218. void IAssetCacheHandle.SetPreloadTag(string addressableName, bool isPreload)
  219. {
  220. Repository.SetPreloadSign(addressableName, isPreload);
  221. }
  222. #region 内部函数
  223. /// <summary>
  224. /// 该监听回调需要保证在IAssetAsync的Completed最后回调
  225. /// 用于释放资源或者Dispose
  226. /// </summary>
  227. /// <param name="aAsync"></param>
  228. void IAsyncListener.OnAsyncCompleted(IAsync aAsync)
  229. {
  230. if (AssetAsyncMap.Count <= 0)
  231. {
  232. if (_unloadunusedOp != OperateState.None)
  233. {
  234. InnerUnloadUnusedAssets();
  235. }
  236. if (_isDispose)
  237. {
  238. var async = _disposeAsync;
  239. InnerDispose();
  240. (async as Async)?.Completed();
  241. }
  242. }
  243. }
  244. private void OnAssetAsyncCompleted(IAsync async)
  245. {
  246. if (async is IAssetAsync assetAsync)
  247. {
  248. AssetAsyncMap.Remove(assetAsync.AddressableName);
  249. var result = assetAsync.GetResult();
  250. if (result != null)
  251. {
  252. var asset = AssetCreator.Create(assetAsync.AddressableName, result);
  253. Repository.AddAsset(asset);
  254. }
  255. }
  256. }
  257. #endregion
  258. }
  259. }