using XGame.Framework.i18n; using System; using System.Collections.Generic; using XGame.Framework.Quality; using XGame.Framework.Asyncs; namespace XGame.Framework.Asset { public sealed partial class AssetManager : IAssetManager, IAsyncListener, IAssetCacheHandle { private enum OperateState : byte { None = 0, Prepare, Start, //End, } AssetRepository Repository { set; get; } Dictionary AssetAsyncMap { set; get; } private List LoadingAsyncs { set; get; } IAssetLoader Loader { set; get; } IAddressableHandle AddressableHandler { set; get; } private LanguageType _languageType; private XQualityLevel _quality; private IAsync _disposeAsync; private bool _isDispose; private OperateState _unloadunusedOp; public AssetManager() { Repository = new AssetRepository(); AssetAsyncMap = new Dictionary(); LoadingAsyncs = new List(); //AsyncPool = new AssetAsyncPool(new AssetAsyncAgentBuilder()); //AsyncPool.AgentLimit = 10; Loader = new LoaderBuilder().Build(); AddressableHandler = Loader as IAddressableHandle; _isDispose = false; _unloadunusedOp = OperateState.None; } TResult IAssetManager.LoadSync(string addressableName) { if (_isDispose) return default; addressableName = AddressableHandler.ConvertAddressableName(new ConvertOptions(){ addressableName = addressableName, quality = _quality, langType = _languageType }); //addressableName?.ToLower(); var result = Repository.Clone(addressableName); if (result != null) { return result.Convert(addressableName); } result = Loader.LoadSync(addressableName); if (result != null) { var asset = AssetCreator.Create(addressableName, result); Repository.AddAsset(asset); result = Repository.Clone(addressableName); return result.Convert(addressableName); } return default; } IAssetLoadAsync IAssetManager.LoadAsync(string addressableName) { if (_isDispose) return default; addressableName = AddressableHandler.ConvertAddressableName(new ConvertOptions() { addressableName = addressableName, quality = _quality, langType = _languageType }); //addressableName?.ToLower(); IAssetAsync assetAsync = null; if (!Repository.ContainsAsset(addressableName)) { //仓库中没找到资源 //先取未完成的async if (!AssetAsyncMap.TryGetValue(addressableName, out assetAsync)) { assetAsync = Loader.LoadAsync(addressableName);//未加载 if (assetAsync != null) { AssetAsyncMap.Add(assetAsync.AddressableName, assetAsync); assetAsync.On(OnAssetAsyncCompleted); //这里多做一个监听,且order要保证该监听在Async的最后执行 assetAsync.On(this, int.MaxValue); } } } // var loadAsync = new AssetLoadAsync(addressableName, assetAsync, this); LoadingAsyncs.Add(loadAsync); return loadAsync; } void IAssetManager.Recycle(object obj) { Repository.Recycle(obj); } void IAssetManager.StopAsync(IAssetLoadAsync async) { //这里只能停止业务的监听事件,不能停止AssetAsync的事件 async.RemoveAll(); //((AssetResultAsync)async).StopAsync(); } void IAssetManager.UnloadUnusedAssets() { if (_unloadunusedOp != OperateState.None) return; if (AssetAsyncMap.Count <= 0) { InnerUnloadUnusedAssets(); } else { _unloadunusedOp = OperateState.Prepare; } } IAsync IAssetManager.LoadSceneBundle(string sceneName) { if (_isDispose || string.IsNullOrEmpty(sceneName)) return default; sceneName = sceneName.ToLower(); IAssetAsync bundleAsync = null; if (!Repository.ContainsAsset(sceneName)) { //仓库中没找到资源 //先取未完成的async if (!AssetAsyncMap.TryGetValue(sceneName, out bundleAsync)) { bundleAsync = Loader.LoadSceneBundleAsync(sceneName);//未加载 if (bundleAsync != null) { AssetAsyncMap.Add(bundleAsync.AddressableName, bundleAsync); bundleAsync.On(OnAssetAsyncCompleted); //这里多做一个监听,且order要保证该监听在Async的最后执行 bundleAsync.On(this, int.MaxValue); } } } return bundleAsync; } void IAssetManager.UnLoadSceneBundle(string sceneName) { Loader.UnLoadSceneBundle(sceneName); } private void InnerUnloadUnusedAssets() { _unloadunusedOp = OperateState.Start; Repository.UnloadUnusedAssets(((assetPath, source) => { Loader.Unload(assetPath, source); })); Loader.UnloadUnusedAssets(); _unloadunusedOp = OperateState.None; } //void IDisposable.Dispose() //{ // //AsyncPool.Dispose(); // Repository.Dispose(); // (Loader as IDisposable)?.Dispose(); // Loader = null; // AssetAsyncMap.Clear(); //} IAsync IAssetManager.Dispose() { var async = new ManagerDisposeAsync(); _isDispose = true; if (AssetAsyncMap.Count == 0) { InnerDispose(); async.Completed(); return async; } _disposeAsync = async; return _disposeAsync; } private void InnerDispose() { Repository.Dispose(); (Loader as IDisposable)?.Dispose(); Loader = null; AddressableHandler = null; AssetAsyncMap.Clear(); for(var i = LoadingAsyncs.Count - 1; i >= 0; i--) { LoadingAsyncs[i].RemoveAll(); } LoadingAsyncs.Clear(); _disposeAsync = null; Monitor.AssetsMonitor.Dispose(); } private void SetLangueType(LanguageType langType) { _languageType = langType; } private void SetQuality(XQualityLevel quality) { _quality = quality; } /// /// 转换AddressableName /// 会根据游戏当前语言、品质等级返回对应的AddressableName /// /// /// string IAssetManager.ConvertAddressableName(string addressableName) { return AddressableHandler?.ConvertAddressableName(new ConvertOptions() { addressableName = addressableName, quality = _quality, langType = _languageType, }) ?? addressableName; } object IAssetCacheHandle.GetAssetFromCache(string addressableName) { return Repository.Clone(addressableName); } void IAssetCacheHandle.ReleaseAsync(IAsync async) { LoadingAsyncs.Remove(async); } void IAssetCacheHandle.SetPreloadTag(string addressableName, bool isPreload) { Repository.SetPreloadSign(addressableName, isPreload); } #region 内部函数 /// /// 该监听回调需要保证在IAssetAsync的Completed最后回调 /// 用于释放资源或者Dispose /// /// void IAsyncListener.OnAsyncCompleted(IAsync aAsync) { if (AssetAsyncMap.Count <= 0) { if (_unloadunusedOp != OperateState.None) { InnerUnloadUnusedAssets(); } if (_isDispose) { var async = _disposeAsync; InnerDispose(); (async as Async)?.Completed(); } } } private void OnAssetAsyncCompleted(IAsync async) { if (async is IAssetAsync assetAsync) { AssetAsyncMap.Remove(assetAsync.AddressableName); var result = assetAsync.GetResult(); if (result != null) { var asset = AssetCreator.Create(assetAsync.AddressableName, result); Repository.AddAsset(asset); } } } #endregion } }