using System; using System.Collections; using System.Collections.Generic; namespace YooAsset { internal class LoadBundleFileOperation : AsyncOperationBase { private enum ESteps { None, CheckConcurrency, LoadBundleFile, Done, } private readonly ResourceManager _resourceManager; private readonly List _providers = new List(100); private readonly List _removeList = new List(100); private FSLoadBundleOperation _loadBundleOp; private ESteps _steps = ESteps.None; /// /// 资源包文件信息 /// public BundleInfo LoadBundleInfo { private set; get; } /// /// 是否已经销毁 /// public bool IsDestroyed { private set; get; } = false; /// /// 引用计数 /// public int RefCount { private set; get; } = 0; /// /// 下载进度 /// public float DownloadProgress { set; get; } = 0; /// /// 下载大小 /// public long DownloadedBytes { set; get; } = 0; /// /// 加载结果 /// public BundleResult Result { set; get; } internal LoadBundleFileOperation(ResourceManager resourceManager, BundleInfo bundleInfo) { _resourceManager = resourceManager; LoadBundleInfo = bundleInfo; } internal override void InternalStart() { _steps = ESteps.CheckConcurrency; } internal override void InternalUpdate() { if (_steps == ESteps.None || _steps == ESteps.Done) return; if (_steps == ESteps.CheckConcurrency) { if (IsWaitForAsyncComplete) { _steps = ESteps.LoadBundleFile; } else { if (_resourceManager.BundleLoadingIsBusy()) return; _steps = ESteps.LoadBundleFile; } } if (_steps == ESteps.LoadBundleFile) { if (_loadBundleOp == null) { _resourceManager.BundleLoadingCounter++; _loadBundleOp = LoadBundleInfo.LoadBundleFile(); _loadBundleOp.StartOperation(); AddChildOperation(_loadBundleOp); } if (IsWaitForAsyncComplete) _loadBundleOp.WaitForAsyncComplete(); _loadBundleOp.UpdateOperation(); DownloadProgress = _loadBundleOp.DownloadProgress; DownloadedBytes = _loadBundleOp.DownloadedBytes; if (_loadBundleOp.IsDone == false) return; if (_loadBundleOp.Status == EOperationStatus.Succeed) { if (_loadBundleOp.Result == null) { _steps = ESteps.Done; Status = EOperationStatus.Failed; Error = $"The bundle loader result is null ! {LoadBundleInfo.Bundle.BundleName}"; } else { _steps = ESteps.Done; Result = _loadBundleOp.Result; Status = EOperationStatus.Succeed; } } else { _steps = ESteps.Done; Status = EOperationStatus.Failed; Error = _loadBundleOp.Error; } // 统计计数减少 _resourceManager.BundleLoadingCounter--; } } internal override void InternalWaitForAsyncComplete() { while (true) { if (ExecuteWhileDone()) { _steps = ESteps.Done; break; } } } internal override string InternalGetDesc() { return $"BundleName : {LoadBundleInfo.Bundle.BundleName}"; } /// /// 引用(引用计数递加) /// public void Reference() { RefCount++; } /// /// 释放(引用计数递减) /// public void Release() { RefCount--; } /// /// 销毁 /// public void DestroyLoader() { IsDestroyed = true; // Check fatal if (RefCount > 0) throw new Exception($"Bundle file loader ref is not zero : {LoadBundleInfo.Bundle.BundleName}"); if (IsDone == false) throw new Exception($"Bundle file loader is not done : {LoadBundleInfo.Bundle.BundleName}"); if (Result != null) Result.UnloadBundleFile(); } /// /// 是否可以销毁 /// public bool CanDestroyLoader() { if (IsDone == false) return false; if (RefCount > 0) return false; // YOOASSET_LEGACY_DEPENDENCY // 检查引用链上的资源包是否已经全部销毁 // 注意:互相引用的资源包无法卸载! if (LoadBundleInfo.Bundle.ReferenceBundleIDs.Count > 0) { foreach (var bundleID in LoadBundleInfo.Bundle.ReferenceBundleIDs) { if (_resourceManager.CheckBundleDestroyed(bundleID) == false) return false; } } return true; } /// /// 添加附属的资源提供者 /// public void AddProvider(ProviderOperation provider) { if (_providers.Contains(provider) == false) _providers.Add(provider); } /// /// 尝试销毁资源提供者 /// public void TryDestroyProviders() { // 获取移除列表 _removeList.Clear(); foreach (var provider in _providers) { if (provider.CanDestroyProvider()) { _removeList.Add(provider); } } // 销毁资源提供者 foreach (var provider in _removeList) { _providers.Remove(provider); provider.DestroyProvider(); } // 移除资源提供者 if (_removeList.Count > 0) { _resourceManager.RemoveBundleProviders(_removeList); _removeList.Clear(); } } } }