Files
Cielonos/Assets/Scripts/MainGame/GameRun/Map/MapManager.cs
SoulliesOfficial 72756712f7 UI调整
2026-05-27 15:15:28 -04:00

158 lines
6.1 KiB
C#
Raw Permalink 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;
using Cielonos.Core.UI;
using Cielonos.MainGame.Characters;
using Cielonos.MainGame.Map;
using DG.Tweening;
using SLSUtilities.General;
using UnityEngine;
using UnityEngine.SceneManagement;
namespace Cielonos.MainGame
{
public partial class MapManager : Singleton<MapManager>
{
public MapBaseCollection baseCollection;
public ZoneData currentZoneData;
public ZoneManager currentZoneManager;
/// <summary>
/// 加载指定 ZoneData 对应的场景,完成后回调 onComplete。
/// 首次加载时跳过淡出(画面已是黑屏),后续切换时先淡出再卸载旧场景。
/// </summary>
/// <param name="nextZoneData">目标 Zone 数据。</param>
/// <param name="onComplete">场景完全就绪后的回调。</param>
/// <param name="skipBattleSetup">
/// 为 true 时跳过敌人生成和 CombatRoomSm.StartRoom()
/// 用于重入已完成的战斗节点(只需重新加载场景环境,无需重新开始战斗)。
/// </param>
public void LoadZone(ZoneData nextZoneData, Action onComplete = null, bool skipBattleSetup = false)
{
StartCoroutine(SwitchRoomRoutine(nextZoneData, onComplete, skipBattleSetup));
}
}
public partial class MapManager
{
public static MapBaseCollection BaseCollection => Instance.baseCollection;
}
public partial class MapManager
{
private IEnumerator SwitchRoomRoutine(ZoneData nextZoneData, Action onComplete, bool skipBattleSetup = false)
{
bool isFirstLoad = currentZoneData == null;
// 0. 禁用玩家输入,防止切换期间误操作
PlayerInputSubcontroller playerInput = MainGameManager.Player.inputSc;
playerInput.inputActions.Player.Disable();
// 1. 淡出画面(首次加载时画面已经是黑屏,无需再 FadeToBlack
if (!isFirstLoad)
{
bool fadeOutComplete = false;
ScreenFader.Instance.FadeToBlack(onComplete: () => fadeOutComplete = true).Play();
yield return new WaitUntil(() => fadeOutComplete);
}
// 2. 异步卸载旧场景
if (!isFirstLoad)
{
yield return SceneManager.UnloadSceneAsync(currentZoneData.sceneName);
}
currentZoneData = nextZoneData;
// 3. 异步加载新场景Additive
string nextSceneName = nextZoneData.sceneName;
AsyncOperation op = SceneManager.LoadSceneAsync(nextSceneName, LoadSceneMode.Additive);
op.allowSceneActivation = false;
while (op.progress < 0.9f)
{
yield return null;
}
op.allowSceneActivation = true;
yield return op;
// 4. 设为活跃场景
Scene nextScene = SceneManager.GetSceneByName(nextSceneName);
SceneManager.SetActiveScene(nextScene);
yield return new WaitForEndOfFrame();
// 5. 重置战斗状态、初始化 Zone
CombatManager.AttackAreaSm.Reset();
CombatManager.CombatRoomSm.Reset();
// 6. 将玩家放置到 playerSpawns 指定的出生点(无论是否跳过战斗均需执行)
SpawnPlayerAtZone(nextZoneData);
if (skipBattleSetup)
{
// 已完成节点仅生成交互物体ExitGate 等),跳过敌人生成和战斗启动
ZoneManager.instance.SetupZoneWithoutEnemies(currentZoneData);
}
else
{
ZoneManager.instance.SetupZone(currentZoneData);
// 等待一帧,让所有 Instantiate 出的敌人执行 Start()
// 将自身 Add 进 activeEnemiesList再启动战斗房间判定。
yield return null;
CombatManager.CombatRoomSm.StartRoom();
}
// 7. 淡入画面
yield return new WaitForSeconds(0.5f);
ScreenFader.Instance?.FadeToClear().Play();
// 8. 恢复玩家输入
playerInput.inputActions.Player.Enable();
// 9. 回调通知调用方RunManager
onComplete?.Invoke();
}
/// <summary>
/// 将玩家传送到 ZoneData.playerSpawns 中随机选择的出生点。
/// 若无配置则回退到原点。
/// </summary>
private void SpawnPlayerAtZone(ZoneData zoneData)
{
Transform playerTransform = MainGameManager.Player.transform;
if (zoneData.playerSpawns == null || zoneData.playerSpawns.Count == 0)
{
Debug.LogWarning("[MapManager] ZoneData 未配置 playerSpawns玩家将放置在原点。");
playerTransform.position = Vector3.zero;
playerTransform.rotation = Quaternion.identity;
return;
}
// 多个出生点时随机选择一个
ZoneData.SpawnPointKey spawnKey = zoneData.playerSpawns.Count == 1
? zoneData.playerSpawns[0]
: zoneData.playerSpawns[UnityEngine.Random.Range(0, zoneData.playerSpawns.Count)];
if (ZoneManager.instance.spawnPoints.TryGetValue(spawnKey.group, out var points)
&& spawnKey.index < points.Count)
{
SpawnPoint point = points[spawnKey.index];
point.GetTransform(out Vector3 position, out Quaternion rotation);
playerTransform.position = position;
playerTransform.rotation = rotation;
Debug.Log($"[MapManager] 玩家放置在出生点 {spawnKey.group}_{spawnKey.index}。");
}
else
{
Debug.LogWarning($"[MapManager] 出生点 '{spawnKey.group}_{spawnKey.index}' 不存在,玩家将放置在原点。");
playerTransform.position = Vector3.zero;
playerTransform.rotation = Quaternion.identity;
}
}
}
}