using System; using System.Collections.Generic; using UnityEngine; /// /// UI面板类型,用于确定面板的层级和行为 /// public enum UIPanelType { Base, // 基础面板(主界面等) Normal, // 普通面板(功能面板) Popup, // 弹出面板(用户管理等) Dialog, // 对话框(确认弹窗等) System // 系统面板(警报覆盖等),最高优先级 } /// /// UI面板信息 /// public class UIPanelInfo { public BasePanel Panel { get; set; } public UIPanelType Type { get; set; } public int Layer { get; set; } public bool IsModal { get; set; } // 是否为模态面板 public string PanelName { get; set; } public UIPanelInfo(BasePanel panel, UIPanelType type, bool isModal = false) { Panel = panel; Type = type; IsModal = isModal; PanelName = panel.GetType().Name; } } /// /// 增强版UI管理器 /// 使用栈管理面板导航,支持层级管理和优雅的返回逻辑 /// public class EnhancedUIManager : MonoBehaviour { #region 单例 private static EnhancedUIManager _instance; public static EnhancedUIManager Instance { get { if (_instance == null) { var go = new GameObject("EnhancedUIManager"); _instance = go.AddComponent(); DontDestroyOnLoad(go); } return _instance; } } #endregion #region 字段和属性 [Header("UI容器")] public Transform CanvasRoot; public Transform BaseLayer; // 基础层(主界面) public Transform NormalLayer; // 普通层(功能面板) public Transform PopupLayer; // 弹窗层(用户管理) public Transform DialogLayer; // 对话框层(确认弹窗) public Transform SystemLayer; // 系统层(警报覆盖) // 面板管理 private Dictionary _allPanels = new Dictionary(); private Stack _navigationStack = new Stack(); private List _activeDialogs = new List(); private UIPanelInfo _currentBasePanel; // 层级管理 private readonly Dictionary _baseLayerValues = new Dictionary { { UIPanelType.Base, 0 }, { UIPanelType.Normal, 100 }, { UIPanelType.Popup, 200 }, { UIPanelType.Dialog, 300 }, { UIPanelType.System, 400 } }; private int _nextLayerIncrement = 0; #endregion #region 初始化 void Awake() { if (_instance == null) { _instance = this; DontDestroyOnLoad(gameObject); InitializeLayers(); } else if (_instance != this) { Destroy(gameObject); } } private void InitializeLayers() { // 查找或创建Canvas if (CanvasRoot == null) { var canvas = FindObjectOfType(); if (canvas == null) { var canvasGO = new GameObject("Canvas"); canvas = canvasGO.AddComponent(); canvas.renderMode = RenderMode.ScreenSpaceOverlay; canvasGO.AddComponent(); canvasGO.AddComponent(); } CanvasRoot = canvas.transform; } // 创建层级 BaseLayer = CreateLayer("BaseLayer", 0); NormalLayer = CreateLayer("NormalLayer", 100); PopupLayer = CreateLayer("PopupLayer", 200); DialogLayer = CreateLayer("DialogLayer", 300); SystemLayer = CreateLayer("SystemLayer", 400); } private Transform CreateLayer(string layerName, int sortingOrder) { var layerGO = new GameObject(layerName); layerGO.transform.SetParent(CanvasRoot, false); var canvas = layerGO.AddComponent(); canvas.overrideSorting = true; canvas.sortingOrder = sortingOrder; layerGO.AddComponent(); // 设置为全屏 var rectTransform = layerGO.GetComponent(); rectTransform.anchorMin = Vector2.zero; rectTransform.anchorMax = Vector2.one; rectTransform.sizeDelta = Vector2.zero; rectTransform.anchoredPosition = Vector2.zero; return layerGO.transform; } #endregion #region 面板显示 /// /// 显示面板 /// public T ShowPanel(UIPanelType panelType = UIPanelType.Normal, bool isModal = false, bool isFade = true) where T : BasePanel { string panelName = typeof(T).Name; // 检查是否已存在 if (_allPanels.ContainsKey(panelName)) { BringPanelToFront(_allPanels[panelName]); return _allPanels[panelName].Panel as T; } // 创建新面板 var panelGO = Instantiate(Resources.Load("UI/" + panelName)); if (panelGO == null) { Debug.LogError($"Failed to load UI prefab: {panelName}"); return null; } var panel = panelGO.GetComponent(); if (panel == null) { Debug.LogError($"Panel {panelName} does not have component {typeof(T)}"); Destroy(panelGO); return null; } // 设置层级 Transform targetLayer = GetTargetLayer(panelType); panelGO.transform.SetParent(targetLayer, false); // 创建面板信息 var panelInfo = new UIPanelInfo(panel, panelType, isModal); panelInfo.Layer = _baseLayerValues[panelType] + _nextLayerIncrement++; // 设置Canvas层级 SetPanelLayer(panelGO, panelInfo.Layer); // 注册面板 _allPanels[panelName] = panelInfo; // 处理导航逻辑 HandlePanelNavigation(panelInfo); // 显示面板 panel.ShowMe(isFade); // Debug.Log($"Showed panel {panelName} at layer {panelInfo.Layer}"); return panel; } private Transform GetTargetLayer(UIPanelType panelType) { return panelType switch { UIPanelType.Base => BaseLayer, UIPanelType.Normal => NormalLayer, UIPanelType.Popup => PopupLayer, UIPanelType.Dialog => DialogLayer, UIPanelType.System => SystemLayer, _ => NormalLayer }; } private void SetPanelLayer(GameObject panelGO, int layer) { var canvas = panelGO.GetComponent(); if (canvas == null) { canvas = panelGO.AddComponent(); panelGO.AddComponent(); } canvas.overrideSorting = true; canvas.sortingOrder = layer; } private void HandlePanelNavigation(UIPanelInfo panelInfo) { switch (panelInfo.Type) { case UIPanelType.Base: // 基础面板,清空导航栈 ClearNavigationStack(); _currentBasePanel = panelInfo; break; case UIPanelType.Normal: case UIPanelType.Popup: // 普通面板,加入导航栈 _navigationStack.Push(panelInfo); break; case UIPanelType.Dialog: // 对话框,加入对话框列表 _activeDialogs.Add(panelInfo); break; case UIPanelType.System: // 系统面板,不影响导航 break; } } #endregion #region 面板关闭 /// /// 关闭面板 /// public void HidePanel(bool isFade = true) where T : BasePanel { string panelName = typeof(T).Name; if (_allPanels.ContainsKey(panelName)) { HidePanel(_allPanels[panelName], isFade); } } private void HidePanel(UIPanelInfo panelInfo, bool isFade = true) { if (panelInfo?.Panel == null) return; // 从导航管理中移除 RemoveFromNavigation(panelInfo); // 隐藏面板 if (isFade) { panelInfo.Panel.HideMe(true, () => { DestroyPanel(panelInfo); }); } else { DestroyPanel(panelInfo); } // Debug.Log($"Hid panel {panelInfo.PanelName}"); } private void RemoveFromNavigation(UIPanelInfo panelInfo) { // 从对话框列表移除 _activeDialogs.Remove(panelInfo); // 从导航栈移除 if (_navigationStack.Contains(panelInfo)) { var tempStack = new Stack(); while (_navigationStack.Count > 0) { var item = _navigationStack.Pop(); if (item != panelInfo) { tempStack.Push(item); } } while (tempStack.Count > 0) { _navigationStack.Push(tempStack.Pop()); } } // 如果是基础面板 if (panelInfo == _currentBasePanel) { _currentBasePanel = null; } } private void DestroyPanel(UIPanelInfo panelInfo) { if (panelInfo?.Panel != null) { Destroy(panelInfo.Panel.gameObject); _allPanels.Remove(panelInfo.PanelName); } } #endregion #region 导航功能 /// /// 返回到主界面 /// public void ReturnToHome() { // 关闭所有非基础面板 var panelsToClose = new List(); foreach (var panel in _allPanels.Values) { if (panel.Type != UIPanelType.Base) { panelsToClose.Add(panel); } } foreach (var panel in panelsToClose) { HidePanel(panel, false); } // 清空导航栈 ClearNavigationStack(); Debug.Log("Returned to home"); } /// /// 返回上一个面板 /// public bool GoBack() { // 优先关闭对话框 if (_activeDialogs.Count > 0) { var lastDialog = _activeDialogs[_activeDialogs.Count - 1]; HidePanel(lastDialog, true); return true; } // 然后处理导航栈 if (_navigationStack.Count > 0) { var currentPanel = _navigationStack.Pop(); HidePanel(currentPanel, true); return true; } return false; } /// /// 关闭所有对话框 /// public void CloseAllDialogs() { var dialogsToClose = new List(_activeDialogs); foreach (var dialog in dialogsToClose) { HidePanel(dialog, false); } } private void ClearNavigationStack() { _navigationStack.Clear(); } private void BringPanelToFront(UIPanelInfo panelInfo) { if (panelInfo?.Panel == null) return; panelInfo.Layer = _baseLayerValues[panelInfo.Type] + _nextLayerIncrement++; SetPanelLayer(panelInfo.Panel.gameObject, panelInfo.Layer); // 重新显示 if (!panelInfo.Panel.gameObject.activeInHierarchy) { panelInfo.Panel.ShowMe(true); } } #endregion #region 实用功能 /// /// 获取面板 /// public T GetPanel() where T : BasePanel { string panelName = typeof(T).Name; if (_allPanels.ContainsKey(panelName)) { return _allPanels[panelName].Panel as T; } return null; } /// /// 检查面板是否显示 /// public bool IsPanelShowing() where T : BasePanel { return GetPanel() != null; } /// /// 获取当前活动面板数量 /// public int GetActivePanelCount() { return _allPanels.Count; } /// /// 获取导航栈深度 /// public int GetNavigationDepth() { return _navigationStack.Count; } /// /// 调试信息 /// public void PrintDebugInfo() { Debug.Log($"=== UI Manager Debug Info ==="); Debug.Log($"Active Panels: {_allPanels.Count}"); Debug.Log($"Navigation Stack Depth: {_navigationStack.Count}"); Debug.Log($"Active Dialogs: {_activeDialogs.Count}"); foreach (var panel in _allPanels.Values) { Debug.Log($"Panel: {panel.PanelName}, Type: {panel.Type}, Layer: {panel.Layer}"); } } #endregion #region Unity事件 void Update() { // 处理返回键 if (Input.GetKeyDown(KeyCode.Escape)) { if (!GoBack()) { // 如果无法返回,可以考虑退出应用或显示退出确认 Debug.Log("Cannot go back further"); } } } #endregion }