From 5e4c574228c7cfadab0931a798d43b085bfb8844 Mon Sep 17 00:00:00 2001
From: yyl <yyl>
Date: 星期五, 26 十二月 2025 18:30:13 +0800
Subject: [PATCH] 125 战斗 休息状态 未加载/被清空预加载资源的问题

---
 Main/System/Battle/BattleField/BattleField.cs              |   17 ++-
 Main/System/Battle/BattleResources/BattleCacheManager.cs   |  198 +++++++++++++++++++++++++++++++++++++-
 Main/System/Battle/BattleField/StoryBattleField.cs         |    1 
 Main/System/Team/TeamHero.cs                               |    1 
 Main/System/Battle/BattleResources/BattlePreloadManager.cs |   33 ++++++
 5 files changed, 234 insertions(+), 16 deletions(-)

diff --git a/Main/System/Battle/BattleField/BattleField.cs b/Main/System/Battle/BattleField/BattleField.cs
index 4728ca5..00bb580 100644
--- a/Main/System/Battle/BattleField/BattleField.cs
+++ b/Main/System/Battle/BattleField/BattleField.cs
@@ -242,16 +242,19 @@
         EventBroadcast.Instance.Broadcast<string>(EventName.BATTLE_START, guid);
     }
 
-    private void PreloadResources(List<TeamBase> redTeamList, List<TeamBase> blueTeamList)
+    protected void PreloadResources(List<TeamBase> redTeamList, List<TeamBase> blueTeamLis)
     {
-        if (blueTeamList == null || blueTeamList.Count <= 0)
-        {
-            return;
-        }
-
+        bool runDirectly = blueTeamLis == null;
         // 浼犻�掓垬鍦篏UID
         PreloadResAction preloadAction = new PreloadResAction(this, redTeamList, blueTeamList);
-        recordPlayer.PlayRecord(preloadAction);
+        if (runDirectly)
+        {
+            preloadAction.Run();
+        }
+        else
+        {
+            recordPlayer.PlayRecord(preloadAction);
+        }
     }
 
     protected virtual void LoadMap(int mapID)
diff --git a/Main/System/Battle/BattleField/StoryBattleField.cs b/Main/System/Battle/BattleField/StoryBattleField.cs
index 516190d..cf12d91 100644
--- a/Main/System/Battle/BattleField/StoryBattleField.cs
+++ b/Main/System/Battle/BattleField/StoryBattleField.cs
@@ -171,6 +171,7 @@
 
     protected void ReloadTeam()
     {
+        PreloadResources(new List<TeamBase>() { TeamManager.Instance.GetTeam(TeamType.Story) }, null);
         battleObjMgr.ReloadTeam(TeamManager.Instance.GetTeam(TeamType.Story), BattleCamp.Red);
     }
 
diff --git a/Main/System/Battle/BattleResources/BattleCacheManager.cs b/Main/System/Battle/BattleResources/BattleCacheManager.cs
index 79682a6..1217833 100644
--- a/Main/System/Battle/BattleResources/BattleCacheManager.cs
+++ b/Main/System/Battle/BattleResources/BattleCacheManager.cs
@@ -72,9 +72,10 @@
             
             if (!globalSpineCache.ContainsKey(key))
             {
+                // 鎶� ResourceIdentifier 鐨� IsPersistent 浼犻�掔粰 CachedResource
                 globalSpineCache[key] = new ResourceReference
                 {
-                    CachedResource = new BattleResCache.CachedResource(res, null, false)
+                    CachedResource = new BattleResCache.CachedResource(res, null, res.IsPersistent)
                 };
             }
             
@@ -91,9 +92,10 @@
             
             if (!globalAudioCache.ContainsKey(key))
             {
+                // 鎶� ResourceIdentifier 鐨� IsPersistent 浼犻�掔粰 CachedResource
                 globalAudioCache[key] = new ResourceReference
                 {
-                    CachedResource = new BattleResCache.CachedResource(res, null, false)
+                    CachedResource = new BattleResCache.CachedResource(res, null, res.IsPersistent)
                 };
             }
             
@@ -106,7 +108,9 @@
     /// <summary>
     /// 娉ㄩ攢鎴樺満锛堝嵏杞借鎴樺満鐨勬墍鏈夎祫婧愬紩鐢級
     /// </summary>
-    public void UnregisterBattlefield(string battleGuid)
+    /// <param name="battleGuid">鎴樺満GUID</param>
+    /// <param name="forceUnloadPersistent">鏄惁寮哄埗鍗歌浇甯搁┗锛堢孩闃燂級璧勬簮锛岄粯璁や负 false</param>
+    public void UnregisterBattlefield(string battleGuid, bool forceUnloadPersistent = false)
     {
         // 澶勭悊Spine璧勬簮
         var spineKeysToRemove = new List<string>();
@@ -116,7 +120,15 @@
             
             if (kvp.Value.RefCount == 0)
             {
-                spineKeysToRemove.Add(kvp.Key);
+                // 浠呭湪闈炲父椹绘垨琚己鍒跺嵏杞芥椂鎵嶇湡姝gЩ闄よ祫婧�
+                if (forceUnloadPersistent || kvp.Value.CachedResource.CanUnload())
+                {
+                    spineKeysToRemove.Add(kvp.Key);
+                }
+                else
+                {
+                    Debug.Log($"BattleCacheManager: Skipped unloading persistent spine resource: {kvp.Key}");
+                }
             }
         }
         
@@ -142,7 +154,15 @@
             
             if (kvp.Value.RefCount == 0)
             {
-                audioKeysToRemove.Add(kvp.Key);
+                // 浠呭湪闈炲父椹绘垨琚己鍒跺嵏杞芥椂鎵嶇湡姝gЩ闄よ祫婧�
+                if (forceUnloadPersistent || kvp.Value.CachedResource.CanUnload())
+                {
+                    audioKeysToRemove.Add(kvp.Key);
+                }
+                else
+                {
+                    Debug.Log($"BattleCacheManager: Skipped unloading persistent audio resource: {kvp.Key}");
+                }
             }
         }
         
@@ -185,12 +205,13 @@
             {
                 Directory = directory,
                 AssetName = assetName,
-                Type = BattleResCache.ResourceType.Spine
+                Type = BattleResCache.ResourceType.Spine,
+                IsPersistent = false // on-demand 鍔犺浇鐨勯粯璁ら潪甯搁┗
             };
             
             globalSpineCache[key] = new ResourceReference
             {
-                CachedResource = new BattleResCache.CachedResource(identifier, asset, false)
+                CachedResource = new BattleResCache.CachedResource(identifier, asset, identifier.IsPersistent)
             };
         }
         
@@ -219,12 +240,13 @@
             {
                 Directory = directory,
                 AssetName = assetName,
-                Type = BattleResCache.ResourceType.Audio
+                Type = BattleResCache.ResourceType.Audio,
+                IsPersistent = false // on-demand 鍔犺浇鐨勯粯璁ら潪甯搁┗
             };
             
             globalAudioCache[key] = new ResourceReference
             {
-                CachedResource = new BattleResCache.CachedResource(identifier, asset, false)
+                CachedResource = new BattleResCache.CachedResource(identifier, asset, identifier.IsPersistent)
             };
         }
         
@@ -236,6 +258,9 @@
     /// </summary>
     public void UpdateResourceReference(string key, BattleResCache.CachedResource resource, string battleGuid, string ownerId)
     {
+        // 纭繚 CachedResource 鐨� IsPersistent 涓� Identifier 涓�鑷�
+        resource.IsPersistent = resource.Identifier.IsPersistent;
+
         if (resource.Identifier.Type == BattleResCache.ResourceType.Spine)
         {
             if (globalSpineCache.ContainsKey(key))
@@ -259,6 +284,161 @@
         
         return $"Spine: {spineTotal}, Audio: {audioTotal}";
     }
+
+    /// <summary>
+    /// 鑾峰彇宸叉敞鍐屽埌鏌愪釜鎴樺満鐨勬墍鏈� OwnerId锛堝彲閫夋嫨鍙繑鍥炲父椹昏祫婧愮殑 owner锛�
+    /// </summary>
+    public HashSet<string> GetRegisteredOwners(string battleGuid, bool onlyPersistent = false)
+    {
+        var owners = new HashSet<string>();
+
+        foreach (var kvp in globalSpineCache)
+        {
+            if (!kvp.Value.BattlefieldOwners.ContainsKey(battleGuid))
+                continue;
+
+            if (onlyPersistent && kvp.Value.CachedResource.IsPersistent == false)
+                continue;
+
+            foreach (var owner in kvp.Value.BattlefieldOwners[battleGuid])
+                owners.Add(owner);
+        }
+
+        foreach (var kvp in globalAudioCache)
+        {
+            if (!kvp.Value.BattlefieldOwners.ContainsKey(battleGuid))
+                continue;
+
+            if (onlyPersistent && kvp.Value.CachedResource.IsPersistent == false)
+                continue;
+
+            foreach (var owner in kvp.Value.BattlefieldOwners[battleGuid])
+                owners.Add(owner);
+        }
+
+        return owners;
+    }
+
+    /// <summary>
+    /// 浠呮敞閿�鎴樺満涓寚瀹氱殑 owner锛堟寜 owner granularity 绉婚櫎锛夛紝浠呭嵏杞藉洜姝ゅ彉涓烘棤浜哄紩鐢ㄧ殑璧勬簮
+    /// </summary>
+    /// <param name="battleGuid">鎴樺満 GUID</param>
+    /// <param name="ownersToRemove">瑕佺Щ闄ょ殑 OwnerId 闆嗗悎</param>
+    public void UnregisterBattlefieldOwners(string battleGuid, HashSet<string> ownersToRemove)
+    {
+        if (ownersToRemove == null || ownersToRemove.Count == 0)
+        {
+            Debug.Log($"BattleCacheManager: UnregisterBattlefieldOwners called with empty owners for {battleGuid}");
+            return;
+        }
+
+        var spineKeysToRemove = new List<string>();
+        foreach (var kvp in globalSpineCache)
+        {
+            if (!kvp.Value.BattlefieldOwners.ContainsKey(battleGuid))
+                continue;
+
+            var owners = kvp.Value.BattlefieldOwners[battleGuid];
+            bool changed = false;
+            foreach (var owner in ownersToRemove)
+            {
+                if (owners.Contains(owner))
+                {
+                    owners.Remove(owner);
+                    changed = true;
+                }
+            }
+
+            if (owners.Count == 0)
+                kvp.Value.BattlefieldOwners.Remove(battleGuid);
+
+            // 濡傛灉鍏ㄥ眬寮曠敤鏁颁负0锛岃鏄庢病鏈変换浣曟垬鍦�/瑙掕壊鍦ㄤ娇鐢ㄨ繖涓祫婧愶紝瀹夊叏鍗歌浇
+            if (kvp.Value.RefCount == 0)
+            {
+                spineKeysToRemove.Add(kvp.Key);
+            }
+            else if (changed)
+            {
+                Debug.Log($"BattleCacheManager: Updated spine owners for {kvp.Key} after removing owners for {battleGuid}");
+            }
+        }
+
+        foreach (var key in spineKeysToRemove)
+        {
+            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 (no owners left): {key}");
+        }
+
+        var audioKeysToRemove = new List<string>();
+        foreach (var kvp in globalAudioCache)
+        {
+            if (!kvp.Value.BattlefieldOwners.ContainsKey(battleGuid))
+                continue;
+
+            var owners = kvp.Value.BattlefieldOwners[battleGuid];
+            bool changed = false;
+            foreach (var owner in ownersToRemove)
+            {
+                if (owners.Contains(owner))
+                {
+                    owners.Remove(owner);
+                    changed = true;
+                }
+            }
+
+            if (owners.Count == 0)
+                kvp.Value.BattlefieldOwners.Remove(battleGuid);
+
+            if (kvp.Value.RefCount == 0)
+            {
+                audioKeysToRemove.Add(kvp.Key);
+            }
+            else if (changed)
+            {
+                Debug.Log($"BattleCacheManager: Updated audio owners for {kvp.Key} after removing owners for {battleGuid}");
+            }
+        }
+
+        foreach (var key in audioKeysToRemove)
+        {
+            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 (no owners left): {key}");
+        }
+
+        Debug.Log($"BattleCacheManager: Unregistered specific owners for battlefield {battleGuid}. Removed owners: {ownersToRemove.Count}");
+    }
+
+    /// <summary>
+    /// 鍒ゆ柇璇ユ垬鍦烘槸鍚﹀凡娉ㄥ唽锛堟湁浠绘剰璧勬簮寮曠敤锛�
+    /// </summary>
+    public bool HasBattleRegistered(string battleGuid)
+    {
+        foreach (var kvp in globalSpineCache)
+        {
+            if (kvp.Value.BattlefieldOwners.ContainsKey(battleGuid)) return true;
+        }
+        foreach (var kvp in globalAudioCache)
+        {
+            if (kvp.Value.BattlefieldOwners.ContainsKey(battleGuid)) return true;
+        }
+        return false;
+    }
     
     // ===== 缂栬緫鍣ㄨ皟璇曟帴鍙� =====
 #if UNITY_EDITOR
diff --git a/Main/System/Battle/BattleResources/BattlePreloadManager.cs b/Main/System/Battle/BattleResources/BattlePreloadManager.cs
index b2fa301..b0ee233 100644
--- a/Main/System/Battle/BattleResources/BattlePreloadManager.cs
+++ b/Main/System/Battle/BattleResources/BattlePreloadManager.cs
@@ -38,6 +38,39 @@
         allSpineResources.AddRange(blueTeamInfo.SpineResources);
         allAudioResources.AddRange(redTeamInfo.AudioResources);
         allAudioResources.AddRange(blueTeamInfo.AudioResources);
+
+        // 妫�鏌ユ槸鍚︿负鍚屼竴鎴樺満鐨勯噸澶嶆敞鍐岋紙姣斿闃熶紞鍙樻洿锛夆�斺�斿鏋滅孩闃熷彂鐢熷彉鏇达紝闇�瑕佸己鍒跺嵏杞戒箣鍓嶇殑甯搁┗璧勬簮
+        if (cacheManager.HasBattleRegistered(battleGuid))
+        {
+            var existingRedOwners = cacheManager.GetRegisteredOwners(battleGuid, true); // 鍙瘮杈冨父椹伙紙绾㈤槦锛�
+            var newRedOwners = new HashSet<string>();
+            foreach (var r in redTeamInfo.SpineResources) if (!string.IsNullOrEmpty(r.OwnerId)) newRedOwners.Add(r.OwnerId);
+            foreach (var r in redTeamInfo.AudioResources) if (!string.IsNullOrEmpty(r.OwnerId)) newRedOwners.Add(r.OwnerId);
+
+            bool different = false;
+            if (existingRedOwners.Count != newRedOwners.Count) different = true;
+            else
+            {
+                foreach (var o in existingRedOwners) if (!newRedOwners.Contains(o)) { different = true; break; }
+            }
+
+            if (different)
+            {
+                // 璁$畻鍝簺 Owner 琚Щ闄わ紝鍙嵏杞借繖浜� Owner 寮曠敤瀵瑰簲鐨勮祫婧愪互鎻愰珮鎬ц兘
+                var removedOwners = new HashSet<string>(existingRedOwners);
+                removedOwners.ExceptWith(newRedOwners);
+
+                if (removedOwners.Count > 0)
+                {
+                    Debug.Log($"BattlePreloadManager: Detected red-team change for {battleGuid}. Removed owners: {removedOwners.Count}. Unloading affected resources only.");
+                    cacheManager.UnregisterBattlefieldOwners(battleGuid, removedOwners);
+                }
+                else
+                {
+                    Debug.Log($"BattlePreloadManager: Detected red-team change for {battleGuid}, but no owners were removed (only additions). No unload necessary.");
+                }
+            }
+        }
         
         cacheManager.RegisterBattlefieldResources(battleGuid, allSpineResources, allAudioResources);
         
diff --git a/Main/System/Team/TeamHero.cs b/Main/System/Team/TeamHero.cs
index 196aa69..3d94074 100644
--- a/Main/System/Team/TeamHero.cs
+++ b/Main/System/Team/TeamHero.cs
@@ -101,6 +101,7 @@
     public TeamHero(HeroInfo heroInfo, int posNum, TeamBase _teamBase)
     {
         heroId = heroInfo.itemHero.config.ID;
+        heroConfig = heroInfo.heroConfig;
         SkinID = heroInfo.SkinID;
         skinConfig = heroInfo.skinConfig;
         Country = heroInfo.heroCountry;

--
Gitblit v1.8.0