feat: 移除自适应性能相关配置并调整动画控制器 移除了Unity自适应性能(Adaptive Performance)的相关配置文件, 包括Adaptive Performance文件夹及其子目录中的所有配置文件, 同时移除了移动通知(NotificationSettings)相关配置, 以及第一章第一关(level_chapter1_level1)的关卡配置文件, 还删除了多个材质文件如AdjustableGlowOrb、AdjustableGlowOrbHalo 和Arena相关材质。另外微调了base-人类士兵.controller中状态机 的位置坐标,将x坐标从320调整为330。 ```
135 lines
4.2 KiB
C#
135 lines
4.2 KiB
C#
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using UnityEngine;
|
|
|
|
/// <summary>
|
|
/// 战斗场景的出战生成:开战前按阵型数据在对应格位生成英雄。
|
|
/// 优先使用阵型编排场景保存的数据;没有编排数据时按名单使用默认阵型(近战前排 / 远程后排)。
|
|
/// </summary>
|
|
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>();
|
|
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<int> 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<UnitTeam>();
|
|
if (team != null)
|
|
{
|
|
team.teamId = playerTeamId;
|
|
}
|
|
|
|
UnitBase unitBase = unit.GetComponent<UnitBase>();
|
|
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<CharacterData>("Data")
|
|
.FirstOrDefault(data => data != null && data.unitPrefab == prefab);
|
|
}
|
|
}
|