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() { 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 void Spawn(GameObject prefab, int cell) { CharacterData characterData = FindCharacterDataForPrefab(prefab); GameObject unit = Instantiate(prefab, DeployGrid.CellPosition(cell), 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)); } } private CharacterData FindCharacterDataForPrefab(GameObject prefab) { if (prefab == null) return null; return Resources.LoadAll("Data") .FirstOrDefault(data => data != null && data.unitPrefab == prefab); } }