Files

158 lines
6.1 KiB
C#
Raw Permalink Normal View History

2026-02-13 09:22:11 -05:00
using System;
using System.Collections;
using Cielonos.Core.UI;
2026-05-10 11:47:55 -04:00
using Cielonos.MainGame.Characters;
2026-02-13 09:22:11 -05:00
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;
2026-05-10 11:47:55 -04:00
2026-02-13 09:22:11 -05:00
public ZoneData currentZoneData;
public ZoneManager currentZoneManager;
2026-05-10 11:47:55 -04:00
/// <summary>
/// 加载指定 ZoneData 对应的场景,完成后回调 onComplete。
/// 首次加载时跳过淡出(画面已是黑屏),后续切换时先淡出再卸载旧场景。
/// </summary>
/// <param name="nextZoneData">目标 Zone 数据。</param>
/// <param name="onComplete">场景完全就绪后的回调。</param>
/// <param name="skipBattleSetup">
2026-05-23 08:27:50 -04:00
/// 为 true 时跳过敌人生成和 CombatRoomSm.StartRoom()
2026-05-10 11:47:55 -04:00
/// 用于重入已完成的战斗节点(只需重新加载场景环境,无需重新开始战斗)。
/// </param>
public void LoadZone(ZoneData nextZoneData, Action onComplete = null, bool skipBattleSetup = false)
2026-02-13 09:22:11 -05:00
{
2026-05-10 11:47:55 -04:00
StartCoroutine(SwitchRoomRoutine(nextZoneData, onComplete, skipBattleSetup));
2026-02-13 09:22:11 -05:00
}
}
public partial class MapManager
{
public static MapBaseCollection BaseCollection => Instance.baseCollection;
}
2026-05-10 11:47:55 -04:00
2026-02-13 09:22:11 -05:00
public partial class MapManager
{
2026-05-10 11:47:55 -04:00
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);
}
2026-02-13 09:22:11 -05:00
// 2. 异步卸载旧场景
2026-05-10 11:47:55 -04:00
if (!isFirstLoad)
{
2026-02-13 09:22:11 -05:00
yield return SceneManager.UnloadSceneAsync(currentZoneData.sceneName);
}
currentZoneData = nextZoneData;
2026-05-10 11:47:55 -04:00
// 3. 异步加载新场景Additive
2026-02-13 09:22:11 -05:00
string nextSceneName = nextZoneData.sceneName;
AsyncOperation op = SceneManager.LoadSceneAsync(nextSceneName, LoadSceneMode.Additive);
2026-05-10 11:47:55 -04:00
op.allowSceneActivation = false;
2026-02-13 09:22:11 -05:00
2026-05-10 11:47:55 -04:00
while (op.progress < 0.9f)
{
yield return null;
2026-02-13 09:22:11 -05:00
}
2026-05-10 11:47:55 -04:00
op.allowSceneActivation = true;
yield return op;
// 4. 设为活跃场景
2026-02-13 09:22:11 -05:00
Scene nextScene = SceneManager.GetSceneByName(nextSceneName);
SceneManager.SetActiveScene(nextScene);
yield return new WaitForEndOfFrame();
2026-05-10 11:47:55 -04:00
// 5. 重置战斗状态、初始化 Zone
2026-05-23 08:27:50 -04:00
CombatManager.AttackAreaSm.Reset();
CombatManager.CombatRoomSm.Reset();
2026-05-10 11:47:55 -04:00
// 6. 将玩家放置到 playerSpawns 指定的出生点(无论是否跳过战斗均需执行)
SpawnPlayerAtZone(nextZoneData);
if (skipBattleSetup)
{
// 已完成节点仅生成交互物体ExitGate 等),跳过敌人生成和战斗启动
ZoneManager.instance.SetupZoneWithoutEnemies(currentZoneData);
}
else
{
ZoneManager.instance.SetupZone(currentZoneData);
// 等待一帧,让所有 Instantiate 出的敌人执行 Start()
// 将自身 Add 进 activeEnemiesList再启动战斗房间判定。
yield return null;
2026-05-23 08:27:50 -04:00
CombatManager.CombatRoomSm.StartRoom();
2026-05-10 11:47:55 -04:00
}
// 7. 淡入画面
2026-02-13 09:22:11 -05:00
yield return new WaitForSeconds(0.5f);
2026-05-27 15:15:28 -04:00
ScreenFader.Instance?.FadeToClear().Play();
2026-05-10 11:47:55 -04:00
// 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;
}
2026-02-13 09:22:11 -05:00
}
}
2026-05-10 11:47:55 -04:00
}