using System.Collections.Generic; using System.Linq; using UnityEngine; /// /// 战斗场景的出战生成:开战前按阵型数据在对应格位生成英雄。 /// 优先使用阵型编排场景保存的数据;没有编排数据时按名单使用默认阵型(近战前排 / 远程后排)。 /// public class BattleFormationSpawner : MonoBehaviour { [Header("出战英雄名单(没有编排数据时的默认来源)")] public HeroRoster roster; [Header("生成到哪个父节点(留空则放在场景根)")] public Transform heroParent; [Header("玩家阵营 ID")] public int playerTeamId = 0; private void Start() { spawnedHeroCount = 0; // 重置计数器 SpawnHeroes(); } private void SpawnHeroes() { // 1. 玩家编排过的阵型 if (FormationData.HasCustomFormation && FormationData.HeroPrefabs != null && FormationData.HeroPrefabs.Length > 0) { for (int i = 0; i < FormationData.HeroPrefabs.Length; i++) { int cell = i < FormationData.CellIndices.Length ? FormationData.CellIndices[i] : -1; if (FormationData.HeroPrefabs[i] == null || !DeployGrid.IsValidIndex(cell)) { continue; } Spawn(FormationData.HeroPrefabs[i], cell); } return; } // 2. 没有编排数据:默认阵型 SpawnDefaultFormation(); } private void SpawnDefaultFormation() { if (roster == null || roster.heroes == null) return; int meleeTotal = 0, rangedTotal = 0; foreach (HeroEntry entry in roster.heroes) { if (entry == null) continue; if (entry.isMelee) meleeTotal++; else rangedTotal++; } var used = new HashSet(); int meleeIndex = 0, rangedIndex = 0; foreach (HeroEntry entry in roster.heroes) { if (entry == null || entry.prefab == null) continue; int cell = entry.isMelee ? DeployGrid.DefaultCell(true, meleeIndex++, meleeTotal) : DeployGrid.DefaultCell(false, rangedIndex++, rangedTotal); if (used.Contains(cell)) { cell = NextFreeCell(cell, used); } if (cell < 0) continue; used.Add(cell); Spawn(entry.prefab, cell); } } private static int NextFreeCell(int from, HashSet used) { for (int i = 0; i < DeployGrid.CellCount; i++) { int candidate = (from + i) % DeployGrid.CellCount; if (!used.Contains(candidate)) return candidate; } return -1; } private static int spawnedHeroCount = 0; // 记录已生成英雄数量 private void Spawn(GameObject prefab, int cell) { CharacterData characterData = FindCharacterDataForPrefab(prefab); Vector3 spawnPos = DeployGrid.CellPosition(cell); GameObject unit = Instantiate(prefab, spawnPos, Quaternion.identity); unit.name = "英雄_" + prefab.name; if (heroParent != null) { unit.transform.SetParent(heroParent, true); } UnitTeam team = unit.GetComponent(); if (team != null) { team.teamId = playerTeamId; } UnitBase unitBase = unit.GetComponent(); if (unitBase != null) { unitBase.returnToAnchorWhenIdle = true; unitBase.anchorArrivalDistance = 0.35f; } if (characterData != null && unitBase != null) { PlayerCharacterData playerData = PlayerDataManager.Instance != null ? PlayerDataManager.Instance.GetCharacterData(characterData.characterId) : null; int level = playerData != null ? playerData.level : 1; unitBase.InitializeFromPlayerData( characterData.GetMaxHealth(level), characterData.GetAttackPower(level), characterData.GetMoveSpeed(level)); } // 设置友方英雄可复活 WorldHealthBar healthBar = unit.GetComponent(); if (healthBar != null && playerTeamId == 0) { healthBar.canRevive = true; } // 绑定到英雄卡片UI BindHeroToCard(unit, characterData, spawnPos); } private void BindHeroToCard(GameObject heroUnit, CharacterData characterData, Vector3 spawnPos) { if (spawnedHeroCount >= 5) return; // 最多5个英雄 // 查找对应的卡片 Canvas canvas = FindObjectOfType(); if (canvas == null) return; Transform heroPanel = canvas.transform.Find("BottomUI/HeroCardsPanel"); if (heroPanel == null) return; string cardName = $"HeroCard{spawnedHeroCount + 1}"; Transform cardObj = heroPanel.Find(cardName); if (cardObj == null) return; HeroCardUI heroCardUI = cardObj.GetComponent(); if (heroCardUI == null) return; // 获取英雄单位组件 UnitBase unitBase = heroUnit.GetComponent(); if (unitBase == null) return; // 加载对应的头像 UnityEngine.Sprite icon = characterData != null ? characterData.cardIcon : null; // 绑定英雄到卡片 heroCardUI.SetHero(unitBase, icon, spawnPos); spawnedHeroCount++; Debug.Log($"英雄 {heroUnit.name} 已绑定到 {cardName}"); } private CharacterData FindCharacterDataForPrefab(GameObject prefab) { if (prefab == null) return null; return Resources.LoadAll("Data") .FirstOrDefault(data => data != null && data.unitPrefab == prefab); } }