Files
Cielonos/Assets/Scripts/MainGame/GameRun/Map/Zone/ZoneManager.cs
SoulliesOfficial 9a9e48f8a5
2026-06-27 12:52:03 -04:00

130 lines
4.9 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);
}
/// <summary>
/// 仅生成交互物体,跳过敌人生成。用于重入已完成的战斗节点。
/// </summary>
public void SetupZoneWithoutEnemies(ZoneData data)
{
SpawnInteractables(data);
}
/// <summary>
/// 根据 ZoneData 中配置的 interactableSpawns 动态生成所有配置的交互物体。
/// </summary>
private void SpawnInteractables(ZoneData data)
{
if (data.interactableSpawns == null) return;
// 遍历关卡数据中配置的每一种交互物定义
foreach (var def in data.interactableSpawns)
{
// 从全局配置合集查找对应的交互物预制体
if (!MapBaseCollection.Interactables.TryGetValue(def.interactableId, out GameObject prefab))
{
Debug.LogWarning($"[ZoneManager] 交互物体 '{def.interactableId}' 在 MapBaseCollection.Interactables 中未找到。");
continue;
}
// 遍历该类型交互物在场景里的所有生成点,逐个进行实例化
foreach (ZoneData.SpawnPointKey key in def.spawnPoints)
{
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}' 不存在,跳过 '{def.interactableId}' 的生成。");
}
}
}
}
}
}