From 5f728e2633e8e20ebafc4e534fe7e7362362c839 Mon Sep 17 00:00:00 2001
From: yyl <yyl>
Date: 星期四, 04 十二月 2025 11:58:07 +0800
Subject: [PATCH] Merge branch 'master' of http://192.168.1.20:10010/r/Project_SG_scripts

---
 Main/System/Battle/BattleResources/BattleCacheManager.cs |  541 +++++++++++++++++++++++++++--------------------------
 1 files changed, 278 insertions(+), 263 deletions(-)

diff --git a/Main/System/Battle/BattleResources/BattleCacheManager.cs b/Main/System/Battle/BattleResources/BattleCacheManager.cs
index 04230a8..79682a6 100644
--- a/Main/System/Battle/BattleResources/BattleCacheManager.cs
+++ b/Main/System/Battle/BattleResources/BattleCacheManager.cs
@@ -5,273 +5,115 @@
 public class BattleCacheManager
 {
     /// <summary>
-    /// 璧勬簮寮曠敤淇℃伅
+    /// 璧勬簮寮曠敤淇℃伅锛堟垬鍦� + 瑙掕壊缁村害锛�
     /// </summary>
     private class ResourceReference
     {
         public BattleResCache.CachedResource CachedResource;
-        public HashSet<string> OwnerIds = new HashSet<string>(); // 浣跨敤璇ヨ祫婧愮殑瑙掕壊ID闆嗗悎
+        // 璁板綍鍝簺鎴樺満鐨勫摢浜涜鑹插湪浣跨敤杩欎釜璧勬簮
+        // Key: battleGuid, Value: ownerIds
+        public Dictionary<string, HashSet<string>> BattlefieldOwners = new Dictionary<string, HashSet<string>>();
         
-        public int RefCount => OwnerIds.Count;
-        
-        public void AddOwner(string ownerId)
+        public int RefCount
         {
-            OwnerIds.Add(ownerId);
+            get
+            {
+                int count = 0;
+                foreach (var owners in BattlefieldOwners.Values)
+                {
+                    count += owners.Count;
+                }
+                return count;
+            }
         }
         
-        public void RemoveOwner(string ownerId)
+        /// <summary>
+        /// 娣诲姞鎴樺満+瑙掕壊鐨勫紩鐢�
+        /// </summary>
+        public void AddBattlefieldOwner(string battleGuid, string ownerId)
         {
-            OwnerIds.Remove(ownerId);
+            if (!BattlefieldOwners.ContainsKey(battleGuid))
+            {
+                BattlefieldOwners[battleGuid] = new HashSet<string>();
+            }
+            BattlefieldOwners[battleGuid].Add(ownerId);
+        }
+        
+        /// <summary>
+        /// 绉婚櫎鏁翠釜鎴樺満鐨勬墍鏈夊紩鐢�
+        /// </summary>
+        public void RemoveBattlefield(string battleGuid)
+        {
+            BattlefieldOwners.Remove(battleGuid);
         }
     }
     
-    // ===== 绾㈤槦璧勬簮锛氬叏灞�鍏变韩锛屾寜寮曠敤璁℃暟绠$悊 =====
-    private static Dictionary<string, ResourceReference> globalRedTeamSpineCache = 
+    // ===== 鍏ㄥ眬缁熶竴璧勬簮姹狅紙涓嶅啀鍖哄垎绾㈣摑闃燂級=====
+    private static Dictionary<string, ResourceReference> globalSpineCache = 
         new Dictionary<string, ResourceReference>();
     
-    private static Dictionary<string, ResourceReference> globalRedTeamAudioCache = 
+    private static Dictionary<string, ResourceReference> globalAudioCache = 
         new Dictionary<string, ResourceReference>();
     
-    // ===== 钃濋槦璧勬簮锛氭寜鎴樺満GUID闅旂 =====
-    private static Dictionary<string, Dictionary<string, BattleResCache.CachedResource>> blueTeamSpineCacheDict = 
-        new Dictionary<string, Dictionary<string, BattleResCache.CachedResource>>();
-    
-    private static Dictionary<string, Dictionary<string, BattleResCache.CachedResource>> blueTeamAudioCacheDict = 
-        new Dictionary<string, Dictionary<string, BattleResCache.CachedResource>>();
-    
     /// <summary>
-    /// 鑾峰彇Spine缂撳瓨锛堢孩闃熷叏灞�锛岃摑闃熸寜鎴樺満闅旂锛�
+    /// 娉ㄥ唽鎴樺満璧勬簮闇�姹傦紙绾㈤槦+钃濋槦涓�璧锋敞鍐岋級
     /// </summary>
-    public Dictionary<string, BattleResCache.CachedResource> GetSpineCache(bool isPersistent, string battleGuid = "")
+    public void RegisterBattlefieldResources(string battleGuid, 
+        List<BattleResCache.ResourceIdentifier> spineResources, 
+        List<BattleResCache.ResourceIdentifier> audioResources)
     {
-        if (isPersistent)
+        // 娉ㄥ唽Spine璧勬簮
+        foreach (var res in spineResources)
         {
-            // 绾㈤槦锛氬皢寮曠敤瀛楀吀杞崲涓烘櫘閫氱紦瀛樺瓧鍏革紙鍏煎鍔犺浇鍣級
-            var cache = new Dictionary<string, BattleResCache.CachedResource>();
-            foreach (var kvp in globalRedTeamSpineCache)
-            {
-                cache[kvp.Key] = kvp.Value.CachedResource;
-            }
-            return cache;
-        }
-        else
-        {
-            // 钃濋槦锛氳繑鍥炴垬鍦轰笓灞炵紦瀛�
-            if (!blueTeamSpineCacheDict.ContainsKey(battleGuid))
-            {
-                blueTeamSpineCacheDict[battleGuid] = new Dictionary<string, BattleResCache.CachedResource>();
-            }
-            return blueTeamSpineCacheDict[battleGuid];
-        }
-    }
-    
-    /// <summary>
-    /// 鑾峰彇闊抽缂撳瓨锛堢孩闃熷叏灞�锛岃摑闃熸寜鎴樺満闅旂锛�
-    /// </summary>
-    public Dictionary<string, BattleResCache.CachedResource> GetAudioCache(bool isPersistent, string battleGuid = "")
-    {
-        if (isPersistent)
-        {
-            // 绾㈤槦锛氬皢寮曠敤瀛楀吀杞崲涓烘櫘閫氱紦瀛樺瓧鍏�
-            var cache = new Dictionary<string, BattleResCache.CachedResource>();
-            foreach (var kvp in globalRedTeamAudioCache)
-            {
-                cache[kvp.Key] = kvp.Value.CachedResource;
-            }
-            return cache;
-        }
-        else
-        {
-            // 钃濋槦锛氳繑鍥炴垬鍦轰笓灞炵紦瀛�
-            if (!blueTeamAudioCacheDict.ContainsKey(battleGuid))
-            {
-                blueTeamAudioCacheDict[battleGuid] = new Dictionary<string, BattleResCache.CachedResource>();
-            }
-            return blueTeamAudioCacheDict[battleGuid];
-        }
-    }
-    
-    /// <summary>
-    /// 娣诲姞绾㈤槦璧勬簮寮曠敤锛堢敱鍔犺浇鍣ㄨ皟鐢級
-    /// </summary>
-    public void AddRedTeamSpineReference(string key, BattleResCache.CachedResource resource, string ownerId)
-    {
-        if (!globalRedTeamSpineCache.ContainsKey(key))
-        {
-            globalRedTeamSpineCache[key] = new ResourceReference
-            {
-                CachedResource = resource
-            };
-        }
-        globalRedTeamSpineCache[key].AddOwner(ownerId);
-    }
-    
-    /// <summary>
-    /// 娣诲姞绾㈤槦闊抽寮曠敤
-    /// </summary>
-    public void AddRedTeamAudioReference(string key, BattleResCache.CachedResource resource, string ownerId)
-    {
-        if (!globalRedTeamAudioCache.ContainsKey(key))
-        {
-            globalRedTeamAudioCache[key] = new ResourceReference
-            {
-                CachedResource = resource
-            };
-        }
-        globalRedTeamAudioCache[key].AddOwner(ownerId);
-    }
-    
-    /// <summary>
-    /// 鑾峰彇Spine璧勬簮锛堟湭鍛戒腑鏃惰嚜鍔ㄥ姞杞藉苟缂撳瓨锛�
-    /// </summary>
-    public SkeletonDataAsset GetSpineResource(string directory, string assetName, string battleGuid = "", bool autoLoadIfMissing = true)
-    {
-        string key = $"{directory}/{assetName}";
-        
-        // 浼樺厛浠庣孩闃熷叏灞�缂撳瓨鏌ユ壘
-        if (globalRedTeamSpineCache.TryGetValue(key, out var redRef))
-        {
-            return redRef.CachedResource.Asset as SkeletonDataAsset;
-        }
-        
-        // 鍐嶄粠钃濋槦鎴樺満涓撳睘缂撳瓨鏌ユ壘
-        if (!string.IsNullOrEmpty(battleGuid) && blueTeamSpineCacheDict.TryGetValue(battleGuid, out var blueCache))
-        {
-            if (blueCache.TryGetValue(key, out var blueRes))
-            {
-                return blueRes.Asset as SkeletonDataAsset;
-            }
-        }
-        
-        // ===== 缂撳瓨鏈懡涓椂鑷姩鍔犺浇 =====
-        if (autoLoadIfMissing)
-        {
-            Debug.LogWarning($"BattleCacheManager: Spine cache miss for {key}, loading on-demand...");
+            if (string.IsNullOrEmpty(res.OwnerId))
+                continue;
+                
+            string key = res.GetKey();
             
-            SkeletonDataAsset asset = ResManager.Instance.LoadAsset<SkeletonDataAsset>(directory, assetName);
-            
-            if (asset != null)
+            if (!globalSpineCache.ContainsKey(key))
             {
-                var identifier = new BattleResCache.ResourceIdentifier
+                globalSpineCache[key] = new ResourceReference
                 {
-                    Directory = directory,
-                    AssetName = assetName,
-                    Type = BattleResCache.ResourceType.Spine,
-                    IsPersistent = string.IsNullOrEmpty(battleGuid)
+                    CachedResource = new BattleResCache.CachedResource(res, null, false)
                 };
-                
-                var cachedRes = new BattleResCache.CachedResource(identifier, asset, identifier.IsPersistent);
-                
-                if (string.IsNullOrEmpty(battleGuid))
-                {
-                    // 绾㈤槦锛氭坊鍔犲紩鐢紙鏈煡鎵�鏈夎�咃紝鐢ㄧ壒娈婃爣璇嗭級
-                    AddRedTeamSpineReference(key, cachedRes, "OnDemand");
-                    Debug.Log($"BattleCacheManager: Added to global red cache: {key}");
-                }
-                else
-                {
-                    // 钃濋槦锛氱洿鎺ュ姞鍏ユ垬鍦虹紦瀛�
-                    if (!blueTeamSpineCacheDict.ContainsKey(battleGuid))
-                    {
-                        blueTeamSpineCacheDict[battleGuid] = new Dictionary<string, BattleResCache.CachedResource>();
-                    }
-                    blueTeamSpineCacheDict[battleGuid][key] = cachedRes;
-                    Debug.Log($"BattleCacheManager: Added to blue cache (BF={battleGuid}): {key}");
-                }
-                
-                return asset;
             }
-        }
-        
-        return null;
-    }
-    
-    /// <summary>
-    /// 鑾峰彇闊抽璧勬簮锛堟湭鍛戒腑鏃惰嚜鍔ㄥ姞杞藉苟缂撳瓨锛�
-    /// </summary>
-    public AudioClip GetAudioResource(string directory, string assetName, string battleGuid = "", bool autoLoadIfMissing = true)
-    {
-        string key = $"{directory}/{assetName}";
-        
-        // 浼樺厛浠庣孩闃熷叏灞�缂撳瓨鏌ユ壘
-        if (globalRedTeamAudioCache.TryGetValue(key, out var redRef))
-        {
-            return redRef.CachedResource.Asset as AudioClip;
-        }
-        
-        // 鍐嶄粠钃濋槦鎴樺満涓撳睘缂撳瓨鏌ユ壘
-        if (!string.IsNullOrEmpty(battleGuid) && blueTeamAudioCacheDict.TryGetValue(battleGuid, out var blueCache))
-        {
-            if (blueCache.TryGetValue(key, out var blueRes))
-            {
-                return blueRes.Asset as AudioClip;
-            }
-        }
-        
-        // ===== 缂撳瓨鏈懡涓椂鑷姩鍔犺浇 =====
-        if (autoLoadIfMissing)
-        {
-            Debug.LogWarning($"BattleCacheManager: Audio cache miss for {key}, loading on-demand...");
             
-            AudioClip asset = ResManager.Instance.LoadAsset<AudioClip>(directory, assetName, false);
+            globalSpineCache[key].AddBattlefieldOwner(battleGuid, res.OwnerId);
+        }
+        
+        // 娉ㄥ唽Audio璧勬簮
+        foreach (var res in audioResources)
+        {
+            if (string.IsNullOrEmpty(res.OwnerId))
+                continue;
+                
+            string key = res.GetKey();
             
-            if (asset != null)
+            if (!globalAudioCache.ContainsKey(key))
             {
-                var identifier = new BattleResCache.ResourceIdentifier
+                globalAudioCache[key] = new ResourceReference
                 {
-                    Directory = directory,
-                    AssetName = assetName,
-                    Type = BattleResCache.ResourceType.Audio,
-                    IsPersistent = string.IsNullOrEmpty(battleGuid)
+                    CachedResource = new BattleResCache.CachedResource(res, null, false)
                 };
-                
-                var cachedRes = new BattleResCache.CachedResource(identifier, asset, identifier.IsPersistent);
-                
-                if (string.IsNullOrEmpty(battleGuid))
-                {
-                    // 绾㈤槦锛氭坊鍔犲紩鐢�
-                    AddRedTeamAudioReference(key, cachedRes, "OnDemand");
-                    Debug.Log($"BattleCacheManager: Added to global red audio cache: {key}");
-                }
-                else
-                {
-                    // 钃濋槦锛氱洿鎺ュ姞鍏ユ垬鍦虹紦瀛�
-                    if (!blueTeamAudioCacheDict.ContainsKey(battleGuid))
-                    {
-                        blueTeamAudioCacheDict[battleGuid] = new Dictionary<string, BattleResCache.CachedResource>();
-                    }
-                    blueTeamAudioCacheDict[battleGuid][key] = cachedRes;
-                    Debug.Log($"BattleCacheManager: Added to blue audio cache (BF={battleGuid}): {key}");
-                }
-                
-                return asset;
             }
+            
+            globalAudioCache[key].AddBattlefieldOwner(battleGuid, res.OwnerId);
         }
         
-        return null;
+        Debug.Log($"BattleCacheManager: Registered battlefield {battleGuid} - Spine: {spineResources.Count}, Audio: {audioResources.Count}");
     }
     
     /// <summary>
-    /// 绉婚櫎鎸囧畾瑙掕壊鐨勭孩闃熻祫婧愬紩鐢�
+    /// 娉ㄩ攢鎴樺満锛堝嵏杞借鎴樺満鐨勬墍鏈夎祫婧愬紩鐢級
     /// </summary>
-    public void RemoveRedTeamReferences(List<string> ownerIds)
+    public void UnregisterBattlefield(string battleGuid)
     {
-        if (ownerIds == null || ownerIds.Count == 0)
-            return;
-        
-        int removedSpineCount = 0;
-        int removedAudioCount = 0;
-        
         // 澶勭悊Spine璧勬簮
         var spineKeysToRemove = new List<string>();
-        foreach (var kvp in globalRedTeamSpineCache)
+        foreach (var kvp in globalSpineCache)
         {
-            foreach (var ownerId in ownerIds)
-            {
-                kvp.Value.RemoveOwner(ownerId);
-            }
+            kvp.Value.RemoveBattlefield(battleGuid);
             
-            // 濡傛灉娌℃湁寮曠敤浜嗭紝鏍囪鍒犻櫎
             if (kvp.Value.RefCount == 0)
             {
                 spineKeysToRemove.Add(kvp.Key);
@@ -280,23 +122,23 @@
         
         foreach (var key in spineKeysToRemove)
         {
-            var resource = globalRedTeamSpineCache[key].CachedResource;
-            ResManager.Instance.UnloadAsset(
-                resource.Identifier.Directory.ToLower(), 
-                resource.Identifier.AssetName.ToLower()
-            );
-            globalRedTeamSpineCache.Remove(key);
-            removedSpineCount++;
+            var res = globalSpineCache[key];
+            if (res.CachedResource.Asset != null)
+            {
+                ResManager.Instance.UnloadAsset(
+                    res.CachedResource.Identifier.Directory, 
+                    res.CachedResource.Identifier.AssetName
+                );
+            }
+            globalSpineCache.Remove(key);
+            Debug.Log($"BattleCacheManager: Unloaded spine (refCount=0): {key}");
         }
         
-        // 澶勭悊闊抽璧勬簮
+        // 澶勭悊Audio璧勬簮
         var audioKeysToRemove = new List<string>();
-        foreach (var kvp in globalRedTeamAudioCache)
+        foreach (var kvp in globalAudioCache)
         {
-            foreach (var ownerId in ownerIds)
-            {
-                kvp.Value.RemoveOwner(ownerId);
-            }
+            kvp.Value.RemoveBattlefield(battleGuid);
             
             if (kvp.Value.RefCount == 0)
             {
@@ -306,55 +148,228 @@
         
         foreach (var key in audioKeysToRemove)
         {
-            var resource = globalRedTeamAudioCache[key].CachedResource;
-            ResManager.Instance.UnloadAsset(
-                resource.Identifier.Directory.ToLower(), 
-                resource.Identifier.AssetName.ToLower()
-            );
-            globalRedTeamAudioCache.Remove(key);
-            removedAudioCount++;
+            var res = globalAudioCache[key];
+            if (res.CachedResource.Asset != null)
+            {
+                ResManager.Instance.UnloadAsset(
+                    res.CachedResource.Identifier.Directory, 
+                    res.CachedResource.Identifier.AssetName
+                );
+            }
+            globalAudioCache.Remove(key);
+            Debug.Log($"BattleCacheManager: Unloaded audio (refCount=0): {key}");
         }
         
-        Debug.Log($"BattleCacheManager: Removed {ownerIds.Count} owner(s), freed {removedSpineCount} spine + {removedAudioCount} audio resources");
+        Debug.Log($"BattleCacheManager: Unregistered battlefield {battleGuid}");
     }
     
     /// <summary>
-    /// 娓呯┖鎸囧畾鎴樺満鐨勮摑闃熺紦瀛�
+    /// 鑾峰彇鎴栧姞杞絊pine璧勬簮
     /// </summary>
-    public void ClearBlueTeamCache(string battleGuid)
+    public SkeletonDataAsset GetSpineResource(string directory, string assetName, string battleGuid = "")
     {
-        if (blueTeamSpineCacheDict.ContainsKey(battleGuid))
+        string key = $"{directory}/{assetName}";
+        
+        if (globalSpineCache.TryGetValue(key, out var refInfo))
         {
-            blueTeamSpineCacheDict.Remove(battleGuid);
+            return refInfo.CachedResource.Asset as SkeletonDataAsset;
         }
         
-        if (blueTeamAudioCacheDict.ContainsKey(battleGuid))
+        // 鑷姩鍔犺浇
+        Debug.LogWarning($"BattleCacheManager: Spine cache miss for {key}, loading on-demand...");
+        var asset = ResManager.Instance.LoadAsset<SkeletonDataAsset>(directory, assetName);
+        
+        if (asset != null)
         {
-            blueTeamAudioCacheDict.Remove(battleGuid);
+            var identifier = new BattleResCache.ResourceIdentifier
+            {
+                Directory = directory,
+                AssetName = assetName,
+                Type = BattleResCache.ResourceType.Spine
+            };
+            
+            globalSpineCache[key] = new ResourceReference
+            {
+                CachedResource = new BattleResCache.CachedResource(identifier, asset, false)
+            };
         }
         
-        Debug.Log($"BattleCacheManager: Cleared blue team cache for battlefield {battleGuid}");
+        return asset;
     }
     
     /// <summary>
-    /// 娓呯┖绾㈤槦鍏ㄥ眬缂撳瓨锛堢帺瀹堕噸缃樀瀹规椂璋冪敤锛�
+    /// 鑾峰彇鎴栧姞杞紸udio璧勬簮
     /// </summary>
-    public void ClearRedTeamCache()
+    public AudioClip GetAudioResource(string directory, string assetName, string battleGuid = "")
     {
-        globalRedTeamSpineCache.Clear();
-        globalRedTeamAudioCache.Clear();
-        Debug.Log("BattleCacheManager: Cleared red team global cache");
+        string key = $"{directory}/{assetName}";
+        
+        if (globalAudioCache.TryGetValue(key, out var refInfo))
+        {
+            return refInfo.CachedResource.Asset as AudioClip;
+        }
+        
+        // 鑷姩鍔犺浇
+        Debug.LogWarning($"BattleCacheManager: Audio cache miss for {key}, loading on-demand...");
+        var asset = ResManager.Instance.LoadAsset<AudioClip>(directory, assetName, false);
+        
+        if (asset != null)
+        {
+            var identifier = new BattleResCache.ResourceIdentifier
+            {
+                Directory = directory,
+                AssetName = assetName,
+                Type = BattleResCache.ResourceType.Audio
+            };
+            
+            globalAudioCache[key] = new ResourceReference
+            {
+                CachedResource = new BattleResCache.CachedResource(identifier, asset, false)
+            };
+        }
+        
+        return asset;
     }
     
     /// <summary>
-    /// 鑾峰彇缂撳瓨缁熻淇℃伅
+    /// 鏇存柊宸插姞杞借祫婧愮殑寮曠敤锛堢敱鍔犺浇鍣ㄨ皟鐢級
     /// </summary>
+    public void UpdateResourceReference(string key, BattleResCache.CachedResource resource, string battleGuid, string ownerId)
+    {
+        if (resource.Identifier.Type == BattleResCache.ResourceType.Spine)
+        {
+            if (globalSpineCache.ContainsKey(key))
+            {
+                globalSpineCache[key].CachedResource = resource;
+            }
+        }
+        else if (resource.Identifier.Type == BattleResCache.ResourceType.Audio)
+        {
+            if (globalAudioCache.ContainsKey(key))
+            {
+                globalAudioCache[key].CachedResource = resource;
+            }
+        }
+    }
+    
     public string GetCacheStats(string battleGuid = "")
     {
-        int blueSpineCount = blueTeamSpineCacheDict.ContainsKey(battleGuid) ? blueTeamSpineCacheDict[battleGuid].Count : 0;
-        int blueAudioCount = blueTeamAudioCacheDict.ContainsKey(battleGuid) ? blueTeamAudioCacheDict[battleGuid].Count : 0;
+        int spineTotal = globalSpineCache.Count;
+        int audioTotal = globalAudioCache.Count;
         
-        return $"Red Spine: {globalRedTeamSpineCache.Count}, Red Audio: {globalRedTeamAudioCache.Count}, " +
-               $"Blue Spine (BF={battleGuid}): {blueSpineCount}, Blue Audio (BF={battleGuid}): {blueAudioCount}";
+        return $"Spine: {spineTotal}, Audio: {audioTotal}";
     }
+    
+    // ===== 缂栬緫鍣ㄨ皟璇曟帴鍙� =====
+#if UNITY_EDITOR
+    // 缂栬緫鍣ㄦā寮忎笅鐨勮祫婧愬紩鐢ㄨ皟璇曠被
+    public class ResourceReferenceDebug
+    {
+        public BattleResCache.CachedResource CachedResource;
+        public Dictionary<string, HashSet<string>> BattlefieldOwners;
+        
+        public int RefCount
+        {
+            get
+            {
+                int count = 0;
+                foreach (var owners in BattlefieldOwners.Values)
+                {
+                    count += owners.Count;
+                }
+                return count;
+            }
+        }
+        
+        // 绉佹湁鏋勯�犲嚱鏁帮紝鍙兘鐢� DebugAPI 璋冪敤
+        internal ResourceReferenceDebug()
+        {
+        }
+    }
+    
+    public static class DebugAPI
+    {
+        public static Dictionary<string, ResourceReferenceDebug> GetSpineCache()
+        {
+            var result = new Dictionary<string, ResourceReferenceDebug>();
+            foreach (var kvp in globalSpineCache)
+            {
+                // 鐩存帴鍦ㄨ繖閲岃祴鍊硷紝涓嶉�氳繃鏋勯�犲嚱鏁颁紶閫掔鏈夌被
+                result[kvp.Key] = new ResourceReferenceDebug
+                {
+                    CachedResource = kvp.Value.CachedResource,
+                    BattlefieldOwners = kvp.Value.BattlefieldOwners
+                };
+            }
+            return result;
+        }
+        
+        public static Dictionary<string, ResourceReferenceDebug> GetAudioCache()
+        {
+            var result = new Dictionary<string, ResourceReferenceDebug>();
+            foreach (var kvp in globalAudioCache)
+            {
+                result[kvp.Key] = new ResourceReferenceDebug
+                {
+                    CachedResource = kvp.Value.CachedResource,
+                    BattlefieldOwners = kvp.Value.BattlefieldOwners
+                };
+            }
+            return result;
+        }
+        
+        public static int GetTotalSpineCount() => globalSpineCache.Count;
+        public static int GetTotalAudioCount() => globalAudioCache.Count;
+        
+        public static HashSet<string> GetAllBattleGuids()
+        {
+            var guids = new HashSet<string>();
+            foreach (var refInfo in globalSpineCache.Values)
+            {
+                foreach (var guid in refInfo.BattlefieldOwners.Keys)
+                {
+                    guids.Add(guid);
+                }
+            }
+            foreach (var refInfo in globalAudioCache.Values)
+            {
+                foreach (var guid in refInfo.BattlefieldOwners.Keys)
+                {
+                    guids.Add(guid);
+                }
+            }
+            return guids;
+        }
+        
+        public static void ClearAllCache()
+        {
+            globalSpineCache.Clear();
+            globalAudioCache.Clear();
+            Debug.Log("BattleCacheManager: All cache cleared (Editor only)");
+        }
+    }
+    
+    // 璧勬簮寮曠敤瑙嗗浘绫伙紙渚涚紪杈戝櫒浣跨敤锛�
+    public class ResourceReferenceView
+    {
+        public string ResourceKey;
+        public string ResourcePath;
+        public bool IsLoaded;
+        public int TotalRefCount;
+        public Dictionary<string, int> BattlefieldRefCounts = new Dictionary<string, int>();
+        
+        public ResourceReferenceView(string key, ResourceReferenceDebug refInfo)
+        {
+            ResourceKey = key;
+            ResourcePath = refInfo.CachedResource.Identifier.Directory + "/" + refInfo.CachedResource.Identifier.AssetName;
+            IsLoaded = refInfo.CachedResource.Asset != null;
+            TotalRefCount = refInfo.RefCount;
+            
+            foreach (var kvp in refInfo.BattlefieldOwners)
+            {
+                BattlefieldRefCounts[kvp.Key] = kvp.Value.Count;
+            }
+        }
+    }
+#endif
 }
\ No newline at end of file

--
Gitblit v1.8.0