Files
Cielonos/Assets/Scripts/MainGame/GameRun/Map/Zone/ZoneManager.cs
2026-05-10 11:47:55 -04:00

130 lines
5.0 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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}' 的生成。");
}
}
}
}
}