using System.Collections.Generic; using UnityEngine; using BaseGames.Core; using BaseGames.Core.Events; namespace BaseGames.UI { [DefaultExecutionOrder(+50)] public class UIManager : MonoBehaviour { [Header("Canvas Roots")] [SerializeField] private GameObject _hudRoot; [SerializeField] private GameObject _pauseMenuRoot; [SerializeField] private GameObject _deathScreenRoot; [SerializeField] private GameObject _settingsRoot; [SerializeField] private GameObject _mapRoot; [SerializeField] private GameObject _shopRoot; [Header("Event Channels")] [SerializeField] private GameStateEventChannelSO _onGameStateChanged; [SerializeField] private VoidEventChannelSO _onPauseRequested; [SerializeField] private VoidEventChannelSO _onFastTravelOpen; [SerializeField] private StringEventChannelSO _onShopOpen; [SerializeField] private VoidEventChannelSO _onMapOpen; private readonly Stack _panelStack = new(); private readonly CompositeDisposable _subs = new(); private void OnEnable() { _onGameStateChanged?.Subscribe(HandleGameStateChanged).AddTo(_subs); _onPauseRequested?.Subscribe(TogglePause).AddTo(_subs); _onFastTravelOpen?.Subscribe(OpenMap).AddTo(_subs); _onShopOpen?.Subscribe(OpenShop).AddTo(_subs); _onMapOpen?.Subscribe(OpenMap).AddTo(_subs); } private void OnDisable() { _subs.Clear(); } private void HandleGameStateChanged(GameStateId state) { // GameStateId 是 struct,用 if/else 而非 switch bool showHud = state == GameStates.Gameplay || state == GameStates.BossFight; if (_hudRoot != null) _hudRoot.SetActive(showHud); if (state == GameStates.Dead) { if (_deathScreenRoot != null) _deathScreenRoot.SetActive(true); } else { // 离开 Dead 状态时(复活/重生)隐藏死亡界面 if (_deathScreenRoot != null) _deathScreenRoot.SetActive(false); if (state == GameStates.Cutscene) if (_hudRoot != null) _hudRoot.SetActive(false); } } public void OpenPanel(GameObject panel) { if (panel == null) return; if (_panelStack.Count > 0) _panelStack.Peek().SetActive(false); panel.SetActive(true); _panelStack.Push(panel); } public void CloseTopPanel() { if (_panelStack.Count == 0) return; _panelStack.Pop().SetActive(false); if (_panelStack.Count > 0) _panelStack.Peek().SetActive(true); } private void TogglePause() { if (_pauseMenuRoot != null && _pauseMenuRoot.activeSelf) CloseTopPanel(); else OpenPanel(_pauseMenuRoot); } private void OpenShop(string _) => OpenPanel(_shopRoot); private void OpenMap() => OpenPanel(_mapRoot); } }