using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Threading.Tasks; using UnityEngine; using UnityEngine.AddressableAssets; using static UnityEngine.AddressableAssets.Addressables; [Serializable] public class TurretResourcesData { public int turretNumber; public string turretName; // 中文名称(如"深海之眼") public int turretType; // 1=普通炮台 2=战神 3=翅膀 public string prefabTurretResourcesPath; // 资源路径(prefab/spine/sprite 共用名) public int animationType; // 1=spine 2=animator 3=animation public int attackAudioID; // 攻击音效 ID public List bulletID; // 子弹 ID 列表 // ---- Addressables 标签 ---- const string turret_AALabel = "PT"; // 炮台统一标签 const string defaultSubLabel = "Default"; // 默认子标签 // ---- 路径→ID 映射(用于 Addressables 加载时反查) ---- private static Dictionary turretPrefabPathDic; // prefabPath → turretNumber private static Dictionary turretSpritePathDic; // spritePath → turretNumber // ---- ID→数据/资源 映射 ---- public static Dictionary turretDataDic; // id → data private static Dictionary turretPrefabDic; // id → prefab private static Dictionary turretSpriteDic; // id → sprite static TurretResourcesData() { Init(); } /// /// 从 Resources/tbturretresources.json 加载炮台元数据。 /// 表里没有的 turretNumber,调用方用 TurretData 自身的 Inspector 默认值,不报错。 /// async static void Init() { turretPrefabPathDic = new Dictionary(); turretSpritePathDic = new Dictionary(); turretDataDic = new Dictionary(); TextAsset jsonAsset = Resources.Load("tbturretresources"); if (jsonAsset == null) { Debug.LogWarning("[TurretResourcesData] 资源表 tbturretresources.json 未找到,炮台数据字典为空,将使用 TurretData 默认值"); return; } try { var list = JsonConvert.DeserializeObject>(jsonAsset.text); if (list == null) { Debug.LogWarning("[TurretResourcesData] 资源表解析为空,将使用 TurretData 默认值"); return; } foreach (var item in list) { if (string.IsNullOrEmpty(item.prefabTurretResourcesPath)) continue; turretPrefabPathDic[item.prefabTurretResourcesPath] = item.turretNumber; turretSpritePathDic[item.prefabTurretResourcesPath] = item.turretNumber; turretDataDic[item.turretNumber] = item; Debug.Log($"[TurretResourcesData] 加载炮台: ID={item.turretNumber}, Path={item.prefabTurretResourcesPath}, Type={item.turretType}, BulletIDs=[{string.Join(",", item.bulletID)}]"); } Debug.Log($"[TurretResourcesData] 初始化完成,共 {turretDataDic.Count} 个炮台配置"); } catch (System.Exception ex) { Debug.LogError($"[TurretResourcesData] JSON 解析失败: {ex.Message},炮台数据字典为空,将使用 TurretData 默认值"); } } // ==================== 资源加载 ==================== /// /// 加载炮台相关 Addressables 资源(PT + Default 标签交集)。 /// public static async Task LoadTurretAssetsData() { turretPrefabDic = new Dictionary(); turretSpriteDic = new Dictionary(); var labels = new List { turret_AALabel, defaultSubLabel }; Debug.Log("[TurretResourcesData] 开始预下载炮台资源依赖 (PT + Default)..."); var depHandle = Addressables.DownloadDependenciesAsync(labels, MergeMode.Intersection); await depHandle.Task; Addressables.Release(depHandle); Debug.Log("[TurretResourcesData] 炮台依赖资源预下载完成!"); // ---- 加载炮台 Prefab ---- var prefabHandle = Addressables.LoadAssetsAsync(labels, prefab => { if (turretPrefabPathDic.TryGetValue(prefab.name, out int id)) { turretPrefabDic[id] = prefab; Debug.Log($"[TurretResourcesData] 加载 Prefab: {prefab.name} (ID={id})"); } }, MergeMode.Intersection); await prefabHandle.Task; Addressables.Release(prefabHandle); Debug.Log($"[TurretResourcesData] 炮台 Prefab 加载完成,共 {turretPrefabDic.Count} 个"); // ---- 加载炮台 Sprite ---- var spriteHandle = Addressables.LoadAssetsAsync(labels, data => { if (turretSpritePathDic.TryGetValue(data.name, out int id)) { turretSpriteDic[id] = data; Debug.Log($"[TurretResourcesData] 加载 Sprite: {data.name} (ID={id})"); } }, MergeMode.Intersection); await spriteHandle.Task; Addressables.Release(spriteHandle); Debug.Log($"[TurretResourcesData] 炮台 Sprite 加载完成,共 {turretSpriteDic.Count} 个"); Debug.Log("[TurretResourcesData] 所有炮台资源加载完毕!"); } /// /// 卸载炮台 Addressables 资源。 /// public static async Task UnLoadTurretAssetsData() { var labels = new List { turret_AALabel, defaultSubLabel }; // 卸载 Prefab var prefabHandle = Addressables.LoadAssetsAsync(labels, null, MergeMode.Intersection); await prefabHandle.Task; if (prefabHandle.Result != null) { foreach (var prefab in prefabHandle.Result) { if (turretPrefabPathDic.TryGetValue(prefab.name, out int id)) { if (turretPrefabDic != null && turretPrefabDic.Remove(id)) Debug.Log($"[TurretResourcesData] 卸载 Prefab: {prefab.name} (ID={id})"); } } } Addressables.Release(prefabHandle); // 卸载 Sprite var spriteHandle = Addressables.LoadAssetsAsync(labels, null, MergeMode.Intersection); await spriteHandle.Task; if (spriteHandle.Result != null) { foreach (var sprite in spriteHandle.Result) { if (turretSpritePathDic.TryGetValue(sprite.name, out int id)) { if (turretSpriteDic != null && turretSpriteDic.Remove(id)) Debug.Log($"[TurretResourcesData] 卸载 Sprite: {sprite.name} (ID={id})"); } } } Addressables.Release(spriteHandle); Debug.Log($"[TurretResourcesData] 卸载完成,剩余 Prefab: {turretPrefabDic?.Count ?? 0}, Sprite: {turretSpriteDic?.Count ?? 0}"); } // ==================== 查询接口 ==================== /// 根据 ID 获取炮台数据。 public static TurretResourcesData GetTurretData(int turretNumber) { return turretDataDic != null && turretDataDic.TryGetValue(turretNumber, out var data) ? data : null; } /// 根据 ID 获取炮台 Prefab。 public static GameObject GetTurretPrefab(int turretNumber) { return turretPrefabDic != null && turretPrefabDic.TryGetValue(turretNumber, out var prefab) ? prefab : null; } /// 根据 ID 获取炮台 Sprite。 public static Sprite GetTurretSprite(int turretNumber) { return turretSpriteDic != null && turretSpriteDic.TryGetValue(turretNumber, out var sprite) ? sprite : null; } /// 获取所有炮台数据列表。 public static List GetAllTurretData() { return turretDataDic != null ? new List(turretDataDic.Values) : new List(); } /// 根据类型获取炮台数据(1=普通炮台, 2=战神, 3=翅膀)。 public static List GetTurretDataByType(int turretType) { var result = new List(); if (turretDataDic == null) return result; foreach (var kv in turretDataDic) { if (kv.Value.turretType == turretType) result.Add(kv.Value); } return result; } }