From 19f1d67a61ee8afb8cab334080bb216ee5ab18ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BD=95=E5=86=A0=E5=B3=B0?= Date: Tue, 9 Sep 2025 18:31:02 +0800 Subject: [PATCH] =?UTF-8?q?feat=20:=20=E5=BC=B1=E5=BC=95=E7=94=A8=E8=B5=84?= =?UTF-8?q?=E6=BA=90=E5=8F=A5=E6=9F=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../YooAsset/Runtime/InitializeParameters.cs | 9 ++ .../Provider/AllAssetsProvider.cs | 2 +- .../ResourceManager/Provider/AssetProvider.cs | 2 +- .../Provider/ProviderOperation.cs | 118 ++++++++++++++++-- .../Provider/SubAssetsProvider.cs | 2 +- .../ResourceManager/ResourceManager.cs | 12 +- 6 files changed, 126 insertions(+), 19 deletions(-) diff --git a/Assets/YooAsset/Runtime/InitializeParameters.cs b/Assets/YooAsset/Runtime/InitializeParameters.cs index 7f7a1d92..058330d1 100644 --- a/Assets/YooAsset/Runtime/InitializeParameters.cs +++ b/Assets/YooAsset/Runtime/InitializeParameters.cs @@ -47,6 +47,15 @@ namespace YooAsset /// WebGL平台强制同步加载资源对象 /// public bool WebGLForceSyncLoadAsset = false; + +#if YOOASSET_EXPERIMENTAL + /// + /// 启用弱引用资源句柄 + /// + public bool UseWeakReferenceHandle = false; +#else + internal bool UseWeakReferenceHandle = false; +#endif } /// diff --git a/Assets/YooAsset/Runtime/ResourceManager/Provider/AllAssetsProvider.cs b/Assets/YooAsset/Runtime/ResourceManager/Provider/AllAssetsProvider.cs index cc8d4ae2..d15aedad 100644 --- a/Assets/YooAsset/Runtime/ResourceManager/Provider/AllAssetsProvider.cs +++ b/Assets/YooAsset/Runtime/ResourceManager/Provider/AllAssetsProvider.cs @@ -17,7 +17,7 @@ namespace YooAsset AddChildOperation(_loadAllAssetsOp); #if UNITY_WEBGL - if (_resManager.WebGLForceSyncLoadAsset()) + if (_resManager.WebGLForceSyncLoadAsset) _loadAllAssetsOp.WaitForAsyncComplete(); #endif } diff --git a/Assets/YooAsset/Runtime/ResourceManager/Provider/AssetProvider.cs b/Assets/YooAsset/Runtime/ResourceManager/Provider/AssetProvider.cs index 8e716a47..58391713 100644 --- a/Assets/YooAsset/Runtime/ResourceManager/Provider/AssetProvider.cs +++ b/Assets/YooAsset/Runtime/ResourceManager/Provider/AssetProvider.cs @@ -17,7 +17,7 @@ namespace YooAsset AddChildOperation(_loadAssetOp); #if UNITY_WEBGL - if (_resManager.WebGLForceSyncLoadAsset()) + if (_resManager.WebGLForceSyncLoadAsset) _loadAssetOp.WaitForAsyncComplete(); #endif } diff --git a/Assets/YooAsset/Runtime/ResourceManager/Provider/ProviderOperation.cs b/Assets/YooAsset/Runtime/ResourceManager/Provider/ProviderOperation.cs index ee3fedd9..c4079dce 100644 --- a/Assets/YooAsset/Runtime/ResourceManager/Provider/ProviderOperation.cs +++ b/Assets/YooAsset/Runtime/ResourceManager/Provider/ProviderOperation.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.Linq; +using System; namespace YooAsset { @@ -72,6 +73,7 @@ namespace YooAsset private readonly LoadBundleFileOperation _mainBundleLoader; private readonly List _bundleLoaders = new List(10); private readonly HashSet _handles = new HashSet(); + private readonly LinkedList> _weakReferences = new LinkedList>(); public ProviderOperation(ResourceManager manager, string providerGUID, AssetInfo assetInfo) { @@ -210,6 +212,11 @@ namespace YooAsset if (_steps == ESteps.ProcessBundleResult) return false; + if (_resManager.UseWeakReferenceHandle) + { + TryCleanupWeakReference(); + } + return RefCount <= 0; } @@ -222,7 +229,15 @@ namespace YooAsset RefCount++; HandleBase handle = HandleFactory.CreateHandle(this, typeof(T)); - _handles.Add(handle); + if (_resManager.UseWeakReferenceHandle) + { + var weakRef = new WeakReference(handle); + _weakReferences.AddLast(weakRef); + } + else + { + _handles.Add(handle); + } return handle as T; } @@ -234,8 +249,16 @@ namespace YooAsset if (RefCount <= 0) throw new System.Exception("Should never get here !"); - if (_handles.Remove(handle) == false) - throw new System.Exception("Should never get here !"); + if (_resManager.UseWeakReferenceHandle) + { + if (RemoveWeakReference(handle) == false) + throw new System.Exception("Should never get here !"); + } + else + { + if (_handles.Remove(handle) == false) + throw new System.Exception("Should never get here !"); + } // 引用计数减少 RefCount--; @@ -246,10 +269,24 @@ namespace YooAsset /// public void ReleaseAllHandles() { - List tempers = _handles.ToList(); - foreach (var handle in tempers) + if (_resManager.UseWeakReferenceHandle) { - handle.Release(); + List> tempers = _weakReferences.ToList(); + foreach (var weakRef in tempers) + { + if (weakRef.TryGetTarget(out HandleBase target)) + { + target.Release(); + } + } + } + else + { + List tempers = _handles.ToList(); + foreach (var handle in tempers) + { + handle.Release(); + } } } @@ -264,12 +301,29 @@ namespace YooAsset // 注意:创建临时列表是为了防止外部逻辑在回调函数内创建或者释放资源句柄。 // 注意:回调方法如果发生异常,会阻断列表里的后续回调方法! - List tempers = _handles.ToList(); - foreach (var hande in tempers) + if (_resManager.UseWeakReferenceHandle) { - if (hande.IsValid) + List> tempers = _weakReferences.ToList(); + foreach (var weakRef in tempers) { - hande.InvokeCallback(); + if (weakRef.TryGetTarget(out HandleBase target)) + { + if (target.IsValid) + { + target.InvokeCallback(); + } + } + } + } + else + { + List tempers = _handles.ToList(); + foreach (var handle in tempers) + { + if (handle.IsValid) + { + handle.InvokeCallback(); + } } } } @@ -294,6 +348,50 @@ namespace YooAsset return status; } + /// + /// 移除指定句柄的弱引用对象 + /// + private bool RemoveWeakReference(HandleBase handle) + { + bool removed = false; + var currentNode = _weakReferences.First; + while (currentNode != null) + { + var nextNode = currentNode.Next; + if (currentNode.Value.TryGetTarget(out HandleBase target)) + { + if (ReferenceEquals(target, handle)) + { + _weakReferences.Remove(currentNode); + removed = true; + break; + } + } + currentNode = nextNode; + } + return removed; + } + + /// + /// 清理所有失效的弱引用 + /// + private void TryCleanupWeakReference() + { + var currentNode = _weakReferences.First; + while (currentNode != null) + { + var nextNode = currentNode.Next; + if (currentNode.Value.TryGetTarget(out HandleBase target) == false) + { + _weakReferences.Remove(currentNode); + + // 引用计数减少 + RefCount--; + } + currentNode = nextNode; + } + } + #region 调试信息 /// /// 出生的场景 diff --git a/Assets/YooAsset/Runtime/ResourceManager/Provider/SubAssetsProvider.cs b/Assets/YooAsset/Runtime/ResourceManager/Provider/SubAssetsProvider.cs index 5127c047..4e2223c9 100644 --- a/Assets/YooAsset/Runtime/ResourceManager/Provider/SubAssetsProvider.cs +++ b/Assets/YooAsset/Runtime/ResourceManager/Provider/SubAssetsProvider.cs @@ -17,7 +17,7 @@ namespace YooAsset AddChildOperation(_loadSubAssetsOp); #if UNITY_WEBGL - if (_resManager.WebGLForceSyncLoadAsset()) + if (_resManager.WebGLForceSyncLoadAsset) _loadSubAssetsOp.WaitForAsyncComplete(); #endif } diff --git a/Assets/YooAsset/Runtime/ResourceManager/ResourceManager.cs b/Assets/YooAsset/Runtime/ResourceManager/ResourceManager.cs index a885d046..baeb02c1 100644 --- a/Assets/YooAsset/Runtime/ResourceManager/ResourceManager.cs +++ b/Assets/YooAsset/Runtime/ResourceManager/ResourceManager.cs @@ -15,7 +15,10 @@ namespace YooAsset private long _sceneCreateIndex = 0; private IBundleQuery _bundleQuery; private int _bundleLoadingMaxConcurrency; - private bool _webGLForceSyncLoadAsset; + + // 开发者配置选项 + public bool WebGLForceSyncLoadAsset { private set; get; } + public bool UseWeakReferenceHandle { private set; get; } /// /// 所属包裹 @@ -44,7 +47,8 @@ namespace YooAsset public void Initialize(InitializeParameters parameters, IBundleQuery bundleServices) { _bundleLoadingMaxConcurrency = parameters.BundleLoadingMaxConcurrency; - _webGLForceSyncLoadAsset = parameters.WebGLForceSyncLoadAsset; + WebGLForceSyncLoadAsset = parameters.WebGLForceSyncLoadAsset; + UseWeakReferenceHandle = parameters.UseWeakReferenceHandle; _bundleQuery = bundleServices; SceneManager.sceneUnloaded += OnSceneUnloaded; } @@ -331,10 +335,6 @@ namespace YooAsset { return BundleLoadingCounter >= _bundleLoadingMaxConcurrency; } - internal bool WebGLForceSyncLoadAsset() - { - return _webGLForceSyncLoadAsset; - } private LoadBundleFileOperation CreateBundleFileLoaderInternal(BundleInfo bundleInfo) {