Files
Cielonos/Assets/Scripts/MainGame/GameRun/Map/Zone/ZoneManager.cs

130 lines
5.0 KiB
C#
Raw Normal View History

2026-02-13 09:22:11 -05:00
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)
{
2026-05-10 11:47:55 -04:00
// 生成敌人
2026-02-13 09:22:11 -05:00
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);
2026-05-10 11:47:55 -04:00
GameObject enemyPrefab = MapBaseCollection.Enemies[enemySpawn.Value];
2026-02-13 09:22:11 -05:00
Instantiate(enemyPrefab, position, rotation);
}
}
}
2026-05-10 11:47:55 -04:00
// 生成交互物体
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}' 的生成。");
}
}
2026-02-13 09:22:11 -05:00
}
}
}