using UnityEngine;
|
using System.Collections.Generic;
|
using Spine.Unity;
|
|
public class BattleCacheManager
|
{
|
/// <summary>
|
/// 资源引用信息(战场 + 角色维度)
|
/// </summary>
|
private class ResourceReference
|
{
|
public BattleResCache.CachedResource CachedResource;
|
// 记录哪些战场的哪些角色在使用这个资源
|
// Key: battleGuid, Value: ownerIds
|
public Dictionary<string, HashSet<string>> BattlefieldOwners = new Dictionary<string, HashSet<string>>();
|
|
public int RefCount
|
{
|
get
|
{
|
int count = 0;
|
foreach (var owners in BattlefieldOwners.Values)
|
{
|
count += owners.Count;
|
}
|
return count;
|
}
|
}
|
|
/// <summary>
|
/// 添加战场+角色的引用
|
/// </summary>
|
public void AddBattlefieldOwner(string battleGuid, string 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> globalSpineCache =
|
new Dictionary<string, ResourceReference>();
|
|
private static Dictionary<string, ResourceReference> globalAudioCache =
|
new Dictionary<string, ResourceReference>();
|
|
/// <summary>
|
/// 注册战场资源需求(红队+蓝队一起注册)
|
/// </summary>
|
public void RegisterBattlefieldResources(string battleGuid,
|
List<BattleResCache.ResourceIdentifier> spineResources,
|
List<BattleResCache.ResourceIdentifier> audioResources)
|
{
|
// 注册Spine资源
|
foreach (var res in spineResources)
|
{
|
if (string.IsNullOrEmpty(res.OwnerId))
|
continue;
|
|
string key = res.GetKey();
|
|
if (!globalSpineCache.ContainsKey(key))
|
{
|
globalSpineCache[key] = new ResourceReference
|
{
|
CachedResource = new BattleResCache.CachedResource(res, null, false)
|
};
|
}
|
|
globalSpineCache[key].AddBattlefieldOwner(battleGuid, res.OwnerId);
|
}
|
|
// 注册Audio资源
|
foreach (var res in audioResources)
|
{
|
if (string.IsNullOrEmpty(res.OwnerId))
|
continue;
|
|
string key = res.GetKey();
|
|
if (!globalAudioCache.ContainsKey(key))
|
{
|
globalAudioCache[key] = new ResourceReference
|
{
|
CachedResource = new BattleResCache.CachedResource(res, null, false)
|
};
|
}
|
|
globalAudioCache[key].AddBattlefieldOwner(battleGuid, res.OwnerId);
|
}
|
|
Debug.Log($"BattleCacheManager: Registered battlefield {battleGuid} - Spine: {spineResources.Count}, Audio: {audioResources.Count}");
|
}
|
|
/// <summary>
|
/// 注销战场(卸载该战场的所有资源引用)
|
/// </summary>
|
public void UnregisterBattlefield(string battleGuid)
|
{
|
// 处理Spine资源
|
var spineKeysToRemove = new List<string>();
|
foreach (var kvp in globalSpineCache)
|
{
|
kvp.Value.RemoveBattlefield(battleGuid);
|
|
if (kvp.Value.RefCount == 0)
|
{
|
spineKeysToRemove.Add(kvp.Key);
|
}
|
}
|
|
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 (refCount=0): {key}");
|
}
|
|
// 处理Audio资源
|
var audioKeysToRemove = new List<string>();
|
foreach (var kvp in globalAudioCache)
|
{
|
kvp.Value.RemoveBattlefield(battleGuid);
|
|
if (kvp.Value.RefCount == 0)
|
{
|
audioKeysToRemove.Add(kvp.Key);
|
}
|
}
|
|
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 (refCount=0): {key}");
|
}
|
|
Debug.Log($"BattleCacheManager: Unregistered battlefield {battleGuid}");
|
}
|
|
/// <summary>
|
/// 获取或加载Spine资源
|
/// </summary>
|
public SkeletonDataAsset GetSpineResource(string directory, string assetName, string battleGuid = "")
|
{
|
string key = $"{directory}/{assetName}";
|
|
if (globalSpineCache.TryGetValue(key, out var refInfo))
|
{
|
return refInfo.CachedResource.Asset as SkeletonDataAsset;
|
}
|
|
// 自动加载
|
Debug.LogWarning($"BattleCacheManager: Spine cache miss for {key}, loading on-demand...");
|
var asset = ResManager.Instance.LoadAsset<SkeletonDataAsset>(directory, assetName);
|
|
if (asset != null)
|
{
|
var identifier = new BattleResCache.ResourceIdentifier
|
{
|
Directory = directory,
|
AssetName = assetName,
|
Type = BattleResCache.ResourceType.Spine
|
};
|
|
globalSpineCache[key] = new ResourceReference
|
{
|
CachedResource = new BattleResCache.CachedResource(identifier, asset, false)
|
};
|
}
|
|
return asset;
|
}
|
|
/// <summary>
|
/// 获取或加载Audio资源
|
/// </summary>
|
public AudioClip GetAudioResource(string directory, string assetName, string battleGuid = "")
|
{
|
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 spineTotal = globalSpineCache.Count;
|
int audioTotal = globalAudioCache.Count;
|
|
return $"Spine: {spineTotal}, Audio: {audioTotal}";
|
}
|
}
|