130 lines
5.0 KiB
C#
130 lines
5.0 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using System.Linq;
|
||
using Sirenix.OdinInspector;
|
||
using SLSUtilities.General;
|
||
using UnityEngine;
|
||
|
||
namespace Cielonos.MainGame.Map
|
||
{
|
||
public partial class ZoneManager : Singleton<ZoneManager>
|
||
{
|
||
[Title("Editor Tools")]
|
||
[Button("Rebuild Spawn Points"), PropertyOrder(-100)]
|
||
public void RebuildMapData()
|
||
{
|
||
if(spawnPointContainer == null)
|
||
{
|
||
Debug.LogWarning("[ZoneManager] Spawn Point Container is not assigned.");
|
||
return;
|
||
}
|
||
|
||
spawnPoints.Clear();
|
||
|
||
// 1. 查找场景中所有生成点
|
||
SpawnPoint[] allPoints = spawnPointContainer.GetComponentsInChildren<SpawnPoint>(true);
|
||
|
||
// 2. 按 groupName 分组,并按 Hierarchy 顺序排序 (保证 Index 确定性)
|
||
var grouped = allPoints
|
||
.GroupBy(p => p.groupName)
|
||
.OrderBy(g => g.Key);
|
||
|
||
foreach (var group in grouped)
|
||
{
|
||
// 按在 Hierarchy 中的顺序排序列表
|
||
var list = group.OrderBy(p => p.transform.GetSiblingIndex()).ToList();
|
||
spawnPoints[group.Key] = list;
|
||
|
||
// 3. 将计算好的 Index 写入到具体物体上(持久化)
|
||
for (int i = 0; i < list.Count; i++)
|
||
{
|
||
list[i].SetData(i); // 调用子物体的方法设置数据
|
||
}
|
||
}
|
||
|
||
//Debug.Log($"[ZoneManager] Rebuilt map: Found {allPoints.Length} points in {spawnPoints.Count} groups.");
|
||
}
|
||
}
|
||
|
||
// 继承 Singleton 保持运行时单例特性
|
||
public partial class ZoneManager
|
||
{
|
||
// 运行时查找用的字典
|
||
[Title("Runtime Data")]
|
||
[Required]
|
||
public GameObject spawnPointContainer;
|
||
public Dictionary<string, List<SpawnPoint>> spawnPoints = new Dictionary<string, List<SpawnPoint>>();
|
||
|
||
protected override void Awake()
|
||
{
|
||
base.Awake();
|
||
RebuildMapData();
|
||
}
|
||
|
||
public void SetupZone(ZoneData data)
|
||
{
|
||
// 生成敌人
|
||
if (data.enemySpawns != null)
|
||
{
|
||
foreach (KeyValuePair<ZoneData.SpawnPointKey, string> enemySpawn in data.enemySpawns)
|
||
{
|
||
string group = enemySpawn.Key.group;
|
||
int index = enemySpawn.Key.index;
|
||
|
||
if (spawnPoints.TryGetValue(group, out List<SpawnPoint> points))
|
||
{
|
||
SpawnPoint point = points[index];
|
||
point.GetTransform(out Vector3 position, out Quaternion rotation);
|
||
GameObject enemyPrefab = MapBaseCollection.Enemies[enemySpawn.Value];
|
||
Instantiate(enemyPrefab, position, rotation);
|
||
}
|
||
}
|
||
}
|
||
|
||
// 生成交互物体
|
||
SpawnInteractables(data.exitSpawns, "Exit");
|
||
SpawnInteractables(data.mechanicalTableSpawns, "MechanicalTable");
|
||
SpawnInteractables(data.logisticsCenterSpawns, "LogisticsCenter");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 仅生成交互物体,跳过敌人生成。用于重入已完成的战斗节点。
|
||
/// </summary>
|
||
public void SetupZoneWithoutEnemies(ZoneData data)
|
||
{
|
||
SpawnInteractables(data.exitSpawns, "Exit");
|
||
SpawnInteractables(data.mechanicalTableSpawns, "MechanicalTable");
|
||
SpawnInteractables(data.logisticsCenterSpawns, "LogisticsCenter");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 根据生成点列表和交互物体 ID,从 MapBaseCollection.Interactables 中实例化交互物体。
|
||
/// </summary>
|
||
/// <param name="spawnKeys">生成点列表。</param>
|
||
/// <param name="interactableId">MapBaseCollection.Interactables 中的键名。</param>
|
||
private void SpawnInteractables(List<ZoneData.SpawnPointKey> spawnKeys, string interactableId)
|
||
{
|
||
if (spawnKeys == null || spawnKeys.Count == 0) return;
|
||
|
||
if (!MapBaseCollection.Interactables.TryGetValue(interactableId, out GameObject prefab))
|
||
{
|
||
Debug.LogWarning($"[ZoneManager] 交互物体 '{interactableId}' 在 MapBaseCollection.Interactables 中未找到。");
|
||
return;
|
||
}
|
||
|
||
foreach (ZoneData.SpawnPointKey key in spawnKeys)
|
||
{
|
||
if (spawnPoints.TryGetValue(key.group, out List<SpawnPoint> points) && key.index < points.Count)
|
||
{
|
||
SpawnPoint point = points[key.index];
|
||
point.GetTransform(out Vector3 position, out Quaternion rotation);
|
||
Instantiate(prefab, position, rotation);
|
||
}
|
||
else
|
||
{
|
||
Debug.LogWarning($"[ZoneManager] 生成点 '{key.group}_{key.index}' 不存在,跳过 '{interactableId}' 的生成。");
|
||
}
|
||
}
|
||
}
|
||
}
|
||
} |