From 194afe435ae761a9d3b8bee4c5268afbca6665d9 Mon Sep 17 00:00:00 2001 From: hevinci Date: Thu, 19 Oct 2023 16:28:30 +0800 Subject: [PATCH] update resource manager MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 增加卸载指定资源的方法。 --- .../Loader/BundleLoaderBase.cs | 63 ++++++++++--------- .../ResourceManager/Provider/ProviderBase.cs | 9 +-- .../ResourceManager/ResourceManager.cs | 50 ++++++++++++++- .../ResourcePackage/Interface/IBundleQuery.cs | 10 +++ .../PlayMode/EditorSimulateModeImpl.cs | 23 +++++++ .../PlayMode/HostPlayModeImpl.cs | 23 +++++++ .../PlayMode/OfflinePlayModeImpl.cs | 23 +++++++ .../PlayMode/WebPlayModeImpl.cs | 23 +++++++ .../ResourcePackage/ResourcePackage.cs | 21 +++++++ 9 files changed, 208 insertions(+), 37 deletions(-) diff --git a/Assets/YooAsset/Runtime/ResourceManager/Loader/BundleLoaderBase.cs b/Assets/YooAsset/Runtime/ResourceManager/Loader/BundleLoaderBase.cs index 8301b44..4c12424 100644 --- a/Assets/YooAsset/Runtime/ResourceManager/Loader/BundleLoaderBase.cs +++ b/Assets/YooAsset/Runtime/ResourceManager/Loader/BundleLoaderBase.cs @@ -45,6 +45,7 @@ namespace YooAsset public bool IsDestroyed { private set; get; } = false; private readonly List _providers = new List(100); + private readonly List _removeList = new List(100); internal AssetBundle CacheBundle { set; get; } internal string FileLoadPath { set; get; } internal float DownloadProgress { set; get; } @@ -59,15 +60,6 @@ namespace YooAsset Status = EStatus.None; } - /// - /// 添加附属的资源提供者 - /// - public void AddProvider(ProviderBase provider) - { - if (_providers.Contains(provider) == false) - _providers.Add(provider); - } - /// /// 引用(引用计数递加) /// @@ -100,40 +92,51 @@ namespace YooAsset if (IsDone() == false) return false; - if (RefCount > 0) - return false; - - return true; + return RefCount <= 0; } /// - /// 在满足条件的前提下,销毁所有资源提供者 + /// 添加附属的资源提供者 /// - public void TryDestroyAllProviders() + public void AddProvider(ProviderBase provider) { + if (_providers.Contains(provider) == false) + _providers.Add(provider); + } + + /// + /// 尝试销毁资源提供者 + /// + public void TryDestroyProviders() + { + // TODO 不用等待资源包加载完成 + /* if (IsDone() == false) return; + */ - // 条件1:必须等待所有Provider可以销毁 + _removeList.Clear(); + + // 获取移除列表 foreach (var provider in _providers) { - if (provider.CanDestroy() == false) - return; - } - - // 条件2:除了自己没有其它引用 - if (RefCount > _providers.Count) - return; - - // 销毁所有Providers - { - foreach (var provider in _providers) + if (provider.CanDestroy()) { - provider.Destroy(); + _removeList.Add(provider); } - Impl.RemoveBundleProviders(_providers); - _providers.Clear(); } + + // 销毁资源提供者 + foreach (var provider in _removeList) + { + _providers.Remove(provider); + provider.Destroy(); + } + + // 移除资源提供者 + Impl.RemoveBundleProviders(_removeList); + + _removeList.Clear(); } diff --git a/Assets/YooAsset/Runtime/ResourceManager/Provider/ProviderBase.cs b/Assets/YooAsset/Runtime/ResourceManager/Provider/ProviderBase.cs index 782bd72..5a6ca6a 100644 --- a/Assets/YooAsset/Runtime/ResourceManager/Provider/ProviderBase.cs +++ b/Assets/YooAsset/Runtime/ResourceManager/Provider/ProviderBase.cs @@ -145,14 +145,15 @@ namespace YooAsset /// public bool CanDestroy() { - if (IsDone == false) + // 注意:在进行资源加载过程时不可以销毁 + if (Status == EStatus.Loading || Status == EStatus.Checking) return false; return RefCount <= 0; } /// - /// 创建操作句柄 + /// 创建资源句柄 /// public T CreateHandle() where T : HandleBase { @@ -178,12 +179,12 @@ namespace YooAsset } /// - /// 释放操作句柄 + /// 释放资源句柄 /// public void ReleaseHandle(HandleBase handle) { if (RefCount <= 0) - YooLogger.Warning("Asset provider reference count is already zero. There may be resource leaks !"); + throw new System.Exception("Should never get here !"); if (_handles.Remove(handle) == false) throw new System.Exception("Should never get here !"); diff --git a/Assets/YooAsset/Runtime/ResourceManager/ResourceManager.cs b/Assets/YooAsset/Runtime/ResourceManager/ResourceManager.cs index a7a8a3a..2bb6b5a 100644 --- a/Assets/YooAsset/Runtime/ResourceManager/ResourceManager.cs +++ b/Assets/YooAsset/Runtime/ResourceManager/ResourceManager.cs @@ -105,7 +105,7 @@ namespace YooAsset for (int i = _loaderList.Count - 1; i >= 0; i--) { BundleLoaderBase loader = _loaderList[i]; - loader.TryDestroyAllProviders(); + loader.TryDestroyProviders(); } for (int i = _loaderList.Count - 1; i >= 0; i--) @@ -121,6 +121,50 @@ namespace YooAsset } } + /// + /// 尝试卸载指定资源的资源包(包括依赖资源) + /// + public void TryUnloadUnusedAsset(AssetInfo assetInfo) + { + if (assetInfo.IsInvalid) + { + YooLogger.Error($"Failed to unload asset ! {assetInfo.Error}"); + return; + } + + // 卸载主资源包加载器 + string manBundleName = _bundleQuery.GetMainBundleName(assetInfo); + var mainLoader = TryGetAssetBundleLoader(manBundleName); + if (mainLoader != null) + { + mainLoader.TryDestroyProviders(); + if (mainLoader.CanDestroy()) + { + string bundleName = mainLoader.MainBundleInfo.Bundle.BundleName; + mainLoader.Destroy(); + _loaderList.Remove(mainLoader); + _loaderDic.Remove(bundleName); + } + } + + // 卸载依赖资源包加载器 + string[] dependBundleNames = _bundleQuery.GetDependBundleNames(assetInfo); + foreach (var dependBundleName in dependBundleNames) + { + var dependLoader = TryGetAssetBundleLoader(dependBundleName); + if (dependLoader != null) + { + if (dependLoader.CanDestroy()) + { + string bundleName = dependLoader.MainBundleInfo.Bundle.BundleName; + dependLoader.Destroy(); + _loaderList.Remove(dependLoader); + _loaderDic.Remove(bundleName); + } + } + } + } + /// /// 强制回收所有资源 /// @@ -357,9 +401,9 @@ namespace YooAsset } return result; } - internal void RemoveBundleProviders(List providers) + internal void RemoveBundleProviders(List removeList) { - foreach (var provider in providers) + foreach (var provider in removeList) { _providerList.Remove(provider); _providerDic.Remove(provider.ProviderGUID); diff --git a/Assets/YooAsset/Runtime/ResourcePackage/Interface/IBundleQuery.cs b/Assets/YooAsset/Runtime/ResourcePackage/Interface/IBundleQuery.cs index b0b5578..6dcab86 100644 --- a/Assets/YooAsset/Runtime/ResourcePackage/Interface/IBundleQuery.cs +++ b/Assets/YooAsset/Runtime/ResourcePackage/Interface/IBundleQuery.cs @@ -13,6 +13,16 @@ namespace YooAsset /// BundleInfo[] GetDependBundleInfos(AssetInfo assetPath); + /// + /// 获取主资源包名称 + /// + string GetMainBundleName(AssetInfo assetInfo); + + /// + /// 获取依赖的资源包名称集合 + /// + string[] GetDependBundleNames(AssetInfo assetInfo); + /// /// 清单是否有效 /// diff --git a/Assets/YooAsset/Runtime/ResourcePackage/PlayMode/EditorSimulateModeImpl.cs b/Assets/YooAsset/Runtime/ResourcePackage/PlayMode/EditorSimulateModeImpl.cs index 3c68027..85ca63a 100644 --- a/Assets/YooAsset/Runtime/ResourcePackage/PlayMode/EditorSimulateModeImpl.cs +++ b/Assets/YooAsset/Runtime/ResourcePackage/PlayMode/EditorSimulateModeImpl.cs @@ -129,6 +129,29 @@ namespace YooAsset } return result.ToArray(); } + string IBundleQuery.GetMainBundleName(AssetInfo assetInfo) + { + if (assetInfo.IsInvalid) + throw new Exception("Should never get here !"); + + // 注意:如果清单里未找到资源包会抛出异常! + var packageBundle = _activeManifest.GetMainPackageBundle(assetInfo.AssetPath); + return packageBundle.BundleName; + } + string[] IBundleQuery.GetDependBundleNames(AssetInfo assetInfo) + { + if (assetInfo.IsInvalid) + throw new Exception("Should never get here !"); + + // 注意:如果清单里未找到资源包会抛出异常! + var depends = _activeManifest.GetAllDependencies(assetInfo.AssetPath); + List result = new List(depends.Length); + foreach (var packageBundle in depends) + { + result.Add(packageBundle.BundleName); + } + return result.ToArray(); + } bool IBundleQuery.ManifestValid() { return _activeManifest != null; diff --git a/Assets/YooAsset/Runtime/ResourcePackage/PlayMode/HostPlayModeImpl.cs b/Assets/YooAsset/Runtime/ResourcePackage/PlayMode/HostPlayModeImpl.cs index eb152b3..6bdc244 100644 --- a/Assets/YooAsset/Runtime/ResourcePackage/PlayMode/HostPlayModeImpl.cs +++ b/Assets/YooAsset/Runtime/ResourcePackage/PlayMode/HostPlayModeImpl.cs @@ -385,6 +385,29 @@ namespace YooAsset } return result.ToArray(); } + string IBundleQuery.GetMainBundleName(AssetInfo assetInfo) + { + if (assetInfo.IsInvalid) + throw new Exception("Should never get here !"); + + // 注意:如果清单里未找到资源包会抛出异常! + var packageBundle = _activeManifest.GetMainPackageBundle(assetInfo.AssetPath); + return packageBundle.BundleName; + } + string[] IBundleQuery.GetDependBundleNames(AssetInfo assetInfo) + { + if (assetInfo.IsInvalid) + throw new Exception("Should never get here !"); + + // 注意:如果清单里未找到资源包会抛出异常! + var depends = _activeManifest.GetAllDependencies(assetInfo.AssetPath); + List result = new List(depends.Length); + foreach (var packageBundle in depends) + { + result.Add(packageBundle.BundleName); + } + return result.ToArray(); + } bool IBundleQuery.ManifestValid() { return _activeManifest != null; diff --git a/Assets/YooAsset/Runtime/ResourcePackage/PlayMode/OfflinePlayModeImpl.cs b/Assets/YooAsset/Runtime/ResourcePackage/PlayMode/OfflinePlayModeImpl.cs index 96b3a2e..bbb1166 100644 --- a/Assets/YooAsset/Runtime/ResourcePackage/PlayMode/OfflinePlayModeImpl.cs +++ b/Assets/YooAsset/Runtime/ResourcePackage/PlayMode/OfflinePlayModeImpl.cs @@ -214,6 +214,29 @@ namespace YooAsset } return result.ToArray(); } + string IBundleQuery.GetMainBundleName(AssetInfo assetInfo) + { + if (assetInfo.IsInvalid) + throw new Exception("Should never get here !"); + + // 注意:如果清单里未找到资源包会抛出异常! + var packageBundle = _activeManifest.GetMainPackageBundle(assetInfo.AssetPath); + return packageBundle.BundleName; + } + string[] IBundleQuery.GetDependBundleNames(AssetInfo assetInfo) + { + if (assetInfo.IsInvalid) + throw new Exception("Should never get here !"); + + // 注意:如果清单里未找到资源包会抛出异常! + var depends = _activeManifest.GetAllDependencies(assetInfo.AssetPath); + List result = new List(depends.Length); + foreach (var packageBundle in depends) + { + result.Add(packageBundle.BundleName); + } + return result.ToArray(); + } bool IBundleQuery.ManifestValid() { return _activeManifest != null; diff --git a/Assets/YooAsset/Runtime/ResourcePackage/PlayMode/WebPlayModeImpl.cs b/Assets/YooAsset/Runtime/ResourcePackage/PlayMode/WebPlayModeImpl.cs index 95d987d..6af106f 100644 --- a/Assets/YooAsset/Runtime/ResourcePackage/PlayMode/WebPlayModeImpl.cs +++ b/Assets/YooAsset/Runtime/ResourcePackage/PlayMode/WebPlayModeImpl.cs @@ -259,6 +259,29 @@ namespace YooAsset } return result.ToArray(); } + string IBundleQuery.GetMainBundleName(AssetInfo assetInfo) + { + if (assetInfo.IsInvalid) + throw new Exception("Should never get here !"); + + // 注意:如果清单里未找到资源包会抛出异常! + var packageBundle = _activeManifest.GetMainPackageBundle(assetInfo.AssetPath); + return packageBundle.BundleName; + } + string[] IBundleQuery.GetDependBundleNames(AssetInfo assetInfo) + { + if (assetInfo.IsInvalid) + throw new Exception("Should never get here !"); + + // 注意:如果清单里未找到资源包会抛出异常! + var depends = _activeManifest.GetAllDependencies(assetInfo.AssetPath); + List result = new List(depends.Length); + foreach (var packageBundle in depends) + { + result.Add(packageBundle.BundleName); + } + return result.ToArray(); + } bool IBundleQuery.ManifestValid() { return _activeManifest != null; diff --git a/Assets/YooAsset/Runtime/ResourcePackage/ResourcePackage.cs b/Assets/YooAsset/Runtime/ResourcePackage/ResourcePackage.cs index 40a7c7c..7a48f19 100644 --- a/Assets/YooAsset/Runtime/ResourcePackage/ResourcePackage.cs +++ b/Assets/YooAsset/Runtime/ResourcePackage/ResourcePackage.cs @@ -346,6 +346,7 @@ namespace YooAsset return _playModeImpl.ActiveManifest.PackageVersion; } + #region 资源卸载 /// /// 资源回收(卸载引用计数为零的资源) /// @@ -355,6 +356,25 @@ namespace YooAsset _resourceMgr.UnloadUnusedAssets(); } + /// + /// 资源回收(尝试卸载指定的资源) + /// + public void TryUnloadUnusedAsset(string location) + { + DebugCheckInitialize(); + AssetInfo assetInfo = ConvertLocationToAssetInfo(location, null); + _resourceMgr.TryUnloadUnusedAsset(assetInfo); + } + + /// + /// 资源回收(尝试卸载指定的资源) + /// + public void TryUnloadUnusedAsset(AssetInfo assetInfo) + { + DebugCheckInitialize(); + _resourceMgr.TryUnloadUnusedAsset(assetInfo); + } + /// /// 强制回收所有资源 /// @@ -363,6 +383,7 @@ namespace YooAsset DebugCheckInitialize(); _resourceMgr.ForceUnloadAllAssets(); } + #endregion #region 沙盒相关 ///