using System.Collections.Generic; using UnityEngine; using System; using System.Collections; /// /// UI管理器 - 支持页面、弹窗和常驻UI的统一管理 /// 新增功能:常驻UI管理、弹窗UI管理、UI组管理、启动配置、状态持久化 /// WebGL兼容版本 - 使用Resources目录加载配置 /// public class UIManager : MonoBehaviour { public static UIManager Instance; [Header("UI根节点")] public Transform pageRoot; // 页面UI根节点 public Transform popupRoot; // 弹窗UI根节点 public Transform fixedRoot; // 常驻UI根节点 [Header("常驻UI配置")] [SerializeField] private bool enableStartupConfig = true; // 是否启用启动配置 [SerializeField] private string configResourcePath = "Config/UI_Config"; // Resources目录下的配置文件路径 // UI字典管理 private Dictionary uiDict = new Dictionary(); private Dictionary fixedUIStates = new Dictionary(); // 常驻UI状态记录 private Dictionary popupUIStates = new Dictionary(); // 弹窗UI状态记录 private Dictionary pageUIStates = new Dictionary(); // 页面UI状态记录 // 配置数据 private UIConfigData uiConfig; // 弹窗管理 private List activePopups = new List(); // 当前活跃的弹窗 private Dictionary autoHideCoroutines = new Dictionary(); // 自动隐藏协程 void Awake() { Instance = this; InitializeUIManager(); } /// /// 初始化UI管理器 /// private void InitializeUIManager() { Debug.Log("UI管理器初始化开始... (完整配置版本)"); // 加载UI配置 if (enableStartupConfig) { LoadUIConfig(); } Debug.Log("UI管理器初始化完成"); } #region 现有API保持不变 public void ShowPage(string uiName, object param = null) { Debug.Log($"开始显示页面: {uiName}"); // 先隐藏其他页面(不包括正要显示的页面) //HideOtherPages(uiName); // 显示指定页面 ShowUI(uiName, pageRoot, param); // 更新状态记录 pageUIStates[uiName] = true; SavePageUIStates(); Debug.Log($"页面已显示: {uiName}"); } public void ShowPopup(string uiName, object param = null) { Debug.Log($"开始显示弹窗: {uiName}"); ShowUI(uiName, popupRoot, param); popupUIStates[uiName] = true; activePopups.Add(uiName); SavePopupUIStates(); // 处理弹窗自动隐藏 HandlePopupAutoHide(uiName); Debug.Log($"弹窗已显示: {uiName}"); } public void HideUI(string uiName) { Debug.Log($"开始隐藏UI: {uiName}"); if (uiDict.TryGetValue(uiName, out UIBase ui)) { // 调用UI的隐藏方法 ui.OnHide(); // 根据UI类型更新状态记录 if (ui.transform.parent == fixedRoot) { fixedUIStates[uiName] = false; SaveFixedUIStates(); Debug.Log($"常驻UI状态已更新: {uiName} = false"); } else if (ui.transform.parent == popupRoot) { popupUIStates[uiName] = false; activePopups.Remove(uiName); SavePopupUIStates(); // 停止自动隐藏协程 StopAutoHideCoroutine(uiName); Debug.Log($"弹窗UI状态已更新: {uiName} = false"); } else if (ui.transform.parent == pageRoot) { pageUIStates[uiName] = false; SavePageUIStates(); Debug.Log($"页面UI状态已更新: {uiName} = false"); } Debug.Log($"UI已隐藏: {uiName}"); } else { Debug.LogWarning($"UI未找到: {uiName}"); } } private void ShowUI(string uiName, Transform parent, object param) { Debug.Log($"开始加载UI: {uiName} 到 {parent.name}"); if (!uiDict.TryGetValue(uiName, out UIBase ui)) { // 加载预制体 GameObject prefab = Resources.Load($"UI/{uiName}"); if (prefab == null) { Debug.LogError($"UI预制体未找到: {uiName}"); return; } // 实例化UI GameObject go = Instantiate(prefab, parent); ui = go.GetComponent(); if (ui == null) { Debug.LogError($"UI预制体 {uiName} 没有UIBase组件"); DestroyImmediate(go); return; } // 添加到字典 uiDict.Add(uiName, ui); Debug.Log($"UI已加载并添加到字典: {uiName}"); } else { Debug.Log($"UI已存在于字典中: {uiName}"); } // 确保UI是激活状态 if (ui.gameObject != null) { ui.gameObject.SetActive(true); } // 调用显示方法 ui.OnShow(param); Debug.Log($"UI显示方法已调用: {uiName}"); } /// /// 隐藏其他页面(不包括指定的页面) /// /// 要排除的UI名称 private void HideOtherPages(string excludeUIName) { Debug.Log($"开始隐藏其他页面(排除: {excludeUIName})"); foreach (var kvp in uiDict) { string uiName = kvp.Key; UIBase ui = kvp.Value; // 跳过要显示的页面 if (uiName == excludeUIName) { Debug.Log($"跳过页面: {uiName}(正要显示)"); continue; } if (ui != null && ui.transform.parent == pageRoot) { Debug.Log($"隐藏页面: {uiName}"); ui.OnHide(); pageUIStates[uiName] = false; } } SavePageUIStates(); Debug.Log("其他页面已隐藏,状态已保存"); } /// /// 隐藏所有页面(包括指定的页面) /// private void HideAllPages() { Debug.Log("开始隐藏所有页面"); foreach (var kvp in uiDict) { string uiName = kvp.Key; UIBase ui = kvp.Value; if (ui != null && ui.transform.parent == pageRoot) { Debug.Log($"隐藏页面: {uiName}"); ui.OnHide(); pageUIStates[uiName] = false; } } SavePageUIStates(); Debug.Log("所有页面已隐藏,状态已保存"); } #endregion #region 新增:常驻UI管理功能 /// /// 显示常驻UI /// /// UI名称 /// 参数 public void ShowFixedUI(string uiName, object param = null) { if (fixedRoot == null) { Debug.LogError("fixedRoot未设置,无法显示常驻UI"); return; } ShowUI(uiName, fixedRoot, param); fixedUIStates[uiName] = true; SaveFixedUIStates(); Debug.Log($"常驻UI已显示: {uiName}"); } /// /// 隐藏常驻UI /// /// UI名称 public void HideFixedUI(string uiName) { if (uiDict.TryGetValue(uiName, out UIBase ui) && ui.transform.parent == fixedRoot) { ui.OnHide(); fixedUIStates[uiName] = false; SaveFixedUIStates(); Debug.Log($"常驻UI已隐藏: {uiName}"); } } /// /// 切换常驻UI显示状态 /// /// UI名称 public void ToggleFixedUI(string uiName) { if (IsFixedUIVisible(uiName)) { HideFixedUI(uiName); } else { ShowFixedUI(uiName); } } /// /// 检查常驻UI是否可见 /// /// UI名称 /// 是否可见 public bool IsFixedUIVisible(string uiName) { return fixedUIStates.TryGetValue(uiName, out bool isVisible) && isVisible; } /// /// 获取所有常驻UI状态 /// /// UI状态字典 public Dictionary GetAllFixedUIStates() { return new Dictionary(fixedUIStates); } #endregion #region 新增:弹窗UI管理功能 /// /// 显示弹窗UI(带自动隐藏) /// /// UI名称 /// 参数 /// 是否自动隐藏 /// 自动隐藏延迟 public void ShowPopupWithAutoHide(string uiName, object param = null, bool autoHide = false, float autoHideDelay = 3.0f) { ShowPopup(uiName, param); if (autoHide) { StartAutoHideCoroutine(uiName, autoHideDelay); } } /// /// 隐藏弹窗UI /// /// UI名称 public void HidePopup(string uiName) { HideUI(uiName); } /// /// 隐藏所有弹窗 /// public void HideAllPopups() { foreach (var popupName in new List(activePopups)) { HidePopup(popupName); } } /// /// 获取当前活跃弹窗数量 /// /// 活跃弹窗数量 public int GetActivePopupCount() { return activePopups.Count; } /// /// 检查弹窗是否可见 /// /// UI名称 /// 是否可见 public bool IsPopupVisible(string uiName) { return popupUIStates.TryGetValue(uiName, out bool isVisible) && isVisible; } /// /// 获取所有弹窗UI状态 /// /// 弹窗状态字典 public Dictionary GetAllPopupUIStates() { return new Dictionary(popupUIStates); } #endregion #region 新增:UI组管理功能 /// /// 显示UI组 /// /// 组名称 public void ShowUIGroup(string groupName) { if (uiConfig?.uiGroups == null) return; var group = uiConfig.uiGroups.Find(g => g.groupName == groupName); if (group != null) { foreach (var uiName in group.uis) { // 根据UI类型决定如何显示 if (IsFixedUI(uiName)) { ShowFixedUI(uiName); } else if (IsPopupUI(uiName)) { ShowPopup(uiName); } else if (IsPageUI(uiName)) { ShowPage(uiName); } } Debug.Log($"UI组已显示: {groupName}"); } } /// /// 隐藏UI组 /// /// 组名称 public void HideUIGroup(string groupName) { if (uiConfig?.uiGroups == null) return; var group = uiConfig.uiGroups.Find(g => g.groupName == groupName); if (group != null) { foreach (var uiName in group.uis) { HideUI(uiName); } Debug.Log($"UI组已隐藏: {groupName}"); } } /// /// 切换UI组显示状态 /// /// 组名称 public void ToggleUIGroup(string groupName) { if (uiConfig?.uiGroups == null) return; var group = uiConfig.uiGroups.Find(g => g.groupName == groupName); if (group != null) { bool isVisible = IsGroupVisible(groupName); if (isVisible) { HideUIGroup(groupName); } else { ShowUIGroup(groupName); } } } /// /// 检查UI组是否可见 /// /// 组名称 /// 是否可见 public bool IsGroupVisible(string groupName) { if (uiConfig?.uiGroups == null) return false; var group = uiConfig.uiGroups.Find(g => g.groupName == groupName); if (group != null) { foreach (var uiName in group.uis) { if (IsUIVisible(uiName)) { return true; // 只要组内有一个UI可见,就认为组可见 } } } return false; } #endregion #region 新增:启动序列管理 /// /// 执行启动序列 /// public void ExecuteStartupSequence() { if (uiConfig?.startupSequence == null) return; StartCoroutine(StartupSequenceCoroutine()); } /// /// 启动序列协程 /// private IEnumerator StartupSequenceCoroutine() { Debug.Log("开始执行启动序列..."); foreach (var step in uiConfig.startupSequence) { yield return new WaitForSeconds(step.delay); switch (step.action) { case "show": ShowUIByName(step.uiName); break; case "hide": HideUI(step.uiName); break; case "showGroup": ShowUIGroup(step.groupName); break; case "hideGroup": HideUIGroup(step.groupName); break; } Debug.Log($"启动序列步骤 {step.step} 完成: {step.action} {step.uiName ?? step.groupName}"); } Debug.Log("启动序列执行完成"); } /// /// 根据名称显示UI(自动判断类型) /// /// UI名称 private void ShowUIByName(string uiName) { if (IsFixedUI(uiName)) { ShowFixedUI(uiName); } else if (IsPopupUI(uiName)) { ShowPopup(uiName); } else if (IsPageUI(uiName)) { ShowPage(uiName); } } #endregion #region 新增:Resources配置系统 /// /// 加载UI配置 /// private void LoadUIConfig() { try { // 从Resources目录加载配置文件 TextAsset configAsset = Resources.Load(configResourcePath); if (configAsset != null) { uiConfig = JsonUtility.FromJson(configAsset.text); Debug.Log($"UI配置已从Resources加载: {configResourcePath}"); // 应用启动配置 ApplyStartupConfig(); // 执行启动序列 if (uiConfig.startupSequence != null && uiConfig.startupSequence.Count > 0) { ExecuteStartupSequence(); } } else { Debug.Log("配置文件未找到,创建了默认UI配置"); } } catch (Exception e) { Debug.LogError($"加载UI配置失败: {e.Message}"); } } /// /// 应用启动配置 /// private void ApplyStartupConfig() { if (uiConfig?.fixedUIs == null) return; Debug.Log("正在应用UI启动配置..."); foreach (var config in uiConfig.fixedUIs) { if (config.visibleOnStart) { ShowFixedUI(config.uiName); } else { // 预加载但不显示 PreloadFixedUI(config.uiName); } } Debug.Log("UI启动配置应用完成"); } /// /// 预加载常驻UI(不显示) /// /// UI名称 private void PreloadFixedUI(string uiName) { if (fixedRoot == null) return; GameObject prefab = Resources.Load($"UI/{uiName}"); if (prefab != null) { GameObject go = Instantiate(prefab, fixedRoot); UIBase ui = go.GetComponent(); if (ui != null) { uiDict[uiName] = ui; go.SetActive(false); // 默认隐藏 fixedUIStates[uiName] = false; Debug.Log($"常驻UI已预加载: {uiName}"); } } } /// /// 重新加载UI配置 /// public void ReloadUIConfig() { LoadUIConfig(); Debug.Log("UI配置已重新加载"); } /// /// 获取当前配置信息 /// /// 配置信息字符串 public string GetConfigInfo() { if (uiConfig?.fixedUIs == null) return "UI配置为空"; string info = "UI配置信息:\n"; info += $"常驻UI数量: {uiConfig.fixedUIs.Count}\n"; info += $"弹窗UI数量: {uiConfig.popupUIs?.Count ?? 0}\n"; info += $"页面UI数量: {uiConfig.pageUIs?.Count ?? 0}\n"; info += $"UI组数量: {uiConfig.uiGroups?.Count ?? 0}\n"; info += $"启动序列步骤: {uiConfig.startupSequence?.Count ?? 0}\n"; return info; } #endregion #region 新增:状态持久化 /// /// 保存常驻UI状态 /// private void SaveFixedUIStates() { try { string statesJson = JsonUtility.ToJson(new FixedUIStates { states = fixedUIStates }); PlayerPrefs.SetString("FixedUIStates", statesJson); PlayerPrefs.Save(); Debug.Log("UI状态已保存到PlayerPrefs"); } catch (Exception e) { Debug.LogError($"保存UI状态失败: {e.Message}"); } } /// /// 保存弹窗UI状态 /// private void SavePopupUIStates() { try { string statesJson = JsonUtility.ToJson(new PopupUIStates { states = popupUIStates }); PlayerPrefs.SetString("PopupUIStates", statesJson); PlayerPrefs.Save(); } catch (Exception e) { Debug.LogError($"保存弹窗UI状态失败: {e.Message}"); } } /// /// 保存页面UI状态 /// private void SavePageUIStates() { try { string statesJson = JsonUtility.ToJson(new PageUIStates { states = pageUIStates }); PlayerPrefs.SetString("PageUIStates", statesJson); PlayerPrefs.Save(); } catch (Exception e) { Debug.LogError($"保存页面UI状态失败: {e.Message}"); } } /// /// 加载常驻UI状态 /// private void LoadFixedUIStates() { try { if (PlayerPrefs.HasKey("FixedUIStates")) { string statesJson = PlayerPrefs.GetString("FixedUIStates"); var statesData = JsonUtility.FromJson(statesJson); fixedUIStates = statesData.states; Debug.Log("UI状态已从PlayerPrefs加载"); } } catch (Exception e) { Debug.LogError($"加载UI状态失败: {e.Message}"); fixedUIStates = new Dictionary(); } } /// /// 重置所有UI状态 /// public void ResetAllUIStates() { fixedUIStates.Clear(); popupUIStates.Clear(); pageUIStates.Clear(); PlayerPrefs.DeleteKey("FixedUIStates"); PlayerPrefs.DeleteKey("PopupUIStates"); PlayerPrefs.DeleteKey("PageUIStates"); PlayerPrefs.Save(); Debug.Log("所有UI状态已重置"); } /// /// 清除所有数据 /// public void ClearAllData() { fixedUIStates.Clear(); popupUIStates.Clear(); pageUIStates.Clear(); PlayerPrefs.DeleteKey("FixedUIStates"); PlayerPrefs.DeleteKey("PopupUIStates"); PlayerPrefs.DeleteKey("PageUIStates"); PlayerPrefs.Save(); Debug.Log("所有数据已清除"); } #endregion #region 新增:弹窗自动隐藏管理 /// /// 处理弹窗自动隐藏 /// /// UI名称 private void HandlePopupAutoHide(string uiName) { if (uiConfig?.popupUIs == null) return; var popupConfig = uiConfig.popupUIs.Find(p => p.uiName == uiName); if (popupConfig != null && popupConfig.autoHide) { StartAutoHideCoroutine(uiName, popupConfig.autoHideDelay); } } /// /// 开始自动隐藏协程 /// /// UI名称 /// 延迟时间 private void StartAutoHideCoroutine(string uiName, float delay) { StopAutoHideCoroutine(uiName); var coroutine = StartCoroutine(AutoHideCoroutine(uiName, delay)); autoHideCoroutines[uiName] = coroutine; } /// /// 停止自动隐藏协程 /// /// UI名称 private void StopAutoHideCoroutine(string uiName) { if (autoHideCoroutines.TryGetValue(uiName, out Coroutine coroutine)) { StopCoroutine(coroutine); autoHideCoroutines.Remove(uiName); } } /// /// 自动隐藏协程 /// /// UI名称 /// 延迟时间 private IEnumerator AutoHideCoroutine(string uiName, float delay) { yield return new WaitForSeconds(delay); if (IsPopupVisible(uiName)) { HidePopup(uiName); Debug.Log($"弹窗 {uiName} 自动隐藏"); } autoHideCoroutines.Remove(uiName); } #endregion #region 新增:UI类型判断 /// /// 判断是否为常驻UI /// /// UI名称 /// 是否为常驻UI private bool IsFixedUI(string uiName) { return uiConfig?.fixedUIs?.Find(u => u.uiName == uiName) != null; } /// /// 判断是否为弹窗UI /// /// UI名称 /// 是否为弹窗UI private bool IsPopupUI(string uiName) { return uiConfig?.popupUIs?.Find(u => u.uiName == uiName) != null; } /// /// 判断是否为页面UI /// /// UI名称 /// 是否为页面UI private bool IsPageUI(string uiName) { return uiConfig?.pageUIs?.Find(u => u.uiName == uiName) != null; } /// /// 检查UI是否可见 /// /// UI名称 /// 是否可见 private bool IsUIVisible(string uiName) { if (IsFixedUI(uiName)) return IsFixedUIVisible(uiName); else if (IsPopupUI(uiName)) return IsPopupVisible(uiName); else if (IsPageUI(uiName)) return pageUIStates.TryGetValue(uiName, out bool isVisible) && isVisible; return false; } #endregion /// /// 重置页面UI状态 /// /// UI名称 public void ResetPageUIState(string uiName) { if (pageUIStates.ContainsKey(uiName)) { pageUIStates[uiName] = false; SavePageUIStates(); Debug.Log($"页面UI状态已重置: {uiName} = false"); } } /// /// 重置所有页面UI状态 /// public void ResetAllPageUIStates() { pageUIStates.Clear(); SavePageUIStates(); Debug.Log("所有页面UI状态已重置"); } /// /// 强制显示页面(忽略状态检查,直接显示) /// /// UI名称 /// 参数 public void ForceShowPage(string uiName, object param = null) { Debug.Log($"强制显示页面: {uiName}"); // 直接显示,不调用HideOtherPages ShowUI(uiName, pageRoot, param); // 强制设置状态为可见 pageUIStates[uiName] = true; SavePageUIStates(); Debug.Log($"页面已强制显示: {uiName}"); } /// /// 安全显示页面(检查状态,避免重复显示) /// /// UI名称 /// 参数 public void SafeShowPage(string uiName, object param = null) { Debug.Log($"安全显示页面: {uiName}"); // 检查是否已经可见 if (IsPageVisible(uiName)) { Debug.Log($"页面 {uiName} 已经可见,无需重复显示"); return; } // 隐藏其他页面 HideOtherPages(uiName); // 显示指定页面 ShowUI(uiName, pageRoot, param); // 更新状态记录 pageUIStates[uiName] = true; SavePageUIStates(); Debug.Log($"页面已安全显示: {uiName}"); } /// /// 检查页面UI是否可见 /// /// UI名称 /// 是否可见 public bool IsPageVisible(string uiName) { return pageUIStates.TryGetValue(uiName, out bool isVisible) && isVisible; } /// /// 获取所有页面UI状态 /// /// 页面状态字典 public Dictionary GetAllPageUIStates() { return new Dictionary(pageUIStates); } /// /// 调试:打印当前所有UI状态 /// public void DebugPrintAllUIStates() { Debug.Log("=== 当前所有UI状态 ==="); Debug.Log("--- 页面UI状态 ---"); foreach (var kvp in pageUIStates) { Debug.Log($"页面: {kvp.Key} = {kvp.Value}"); } Debug.Log("--- 弹窗UI状态 ---"); foreach (var kvp in popupUIStates) { Debug.Log($"弹窗: {kvp.Key} = {kvp.Value}"); } Debug.Log("--- 常驻UI状态 ---"); foreach (var kvp in fixedUIStates) { Debug.Log($"常驻: {kvp.Key} = {kvp.Value}"); } Debug.Log("=================="); } /// /// 获取UI管理器状态信息 /// /// 状态信息字符串 public string GetStatusInfo() { return $"UI管理器状态 - 页面UI: {GetUICount(pageRoot)}, 弹窗UI: {GetUICount(popupRoot)}, 常驻UI: {GetUICount(fixedRoot)}, 活跃弹窗: {GetActivePopupCount()}"; } private int GetUICount(Transform root) { return root != null ? root.childCount : 0; } } #region 配置数据结构 /// /// UI配置数据 /// [Serializable] public class UIConfigData { public List fixedUIs = new List(); public List popupUIs = new List(); public List pageUIs = new List(); public List uiGroups = new List(); public List startupSequence = new List(); public DefaultSettingsConfig defaultSettings = new DefaultSettingsConfig(); } /// /// 常驻UI配置 /// [Serializable] public class FixedUIConfig { public string uiName; // UI名称 public bool visibleOnStart; // 启动时是否可见 public string description; // 描述 } /// /// 弹窗UI配置 /// [Serializable] public class PopupUIConfig { public string uiName; // UI名称 public bool visibleOnStart; // 启动时是否可见 public bool autoHide; // 是否自动隐藏 public float autoHideDelay; // 自动隐藏延迟 public int priority; // 优先级 public int layer; // 显示层级 public string description; // 描述 } /// /// 页面UI配置 /// [Serializable] public class PageUIConfig { public string uiName; // UI名称 public bool visibleOnStart; // 启动时是否可见 public bool canStack; // 是否可以叠加 public string description; // 描述 } /// /// UI组配置 /// [Serializable] public class UIGroupConfig { public string groupName; // 组名称 public List uis; // UI名称列表 public bool visibleOnStart; // 启动时是否可见 public string description; // 描述 } /// /// 启动步骤配置 /// [Serializable] public class StartupStepConfig { public int step; // 步骤序号 public string action; // 动作类型 public string uiName; // UI名称 public string groupName; // 组名称 public float delay; // 延迟时间 public string description; // 描述 } /// /// 默认设置配置 /// [Serializable] public class DefaultSettingsConfig { public float fadeInDuration = 0.3f; // 淡入时长 public float fadeOutDuration = 0.3f; // 淡出时长 public bool enableAnimations = true; // 是否启用动画 public bool saveUserPreferences = true; // 是否保存用户偏好 public bool autoHideEnabled = true; // 是否启用自动隐藏 public int maxPopupCount = 5; // 最大弹窗数量 public int defaultPopupLayer = 100; // 默认弹窗层级 } /// /// 常驻UI状态数据 /// [Serializable] public class FixedUIStates { public Dictionary states = new Dictionary(); } /// /// 弹窗UI状态数据 /// [Serializable] public class PopupUIStates { public Dictionary states = new Dictionary(); } /// /// 页面UI状态数据 /// [Serializable] public class PageUIStates { public Dictionary states = new Dictionary(); } #endregion