1143 lines
31 KiB
C#
1143 lines
31 KiB
C#
using System.Collections.Generic;
|
||
using UnityEngine;
|
||
using System;
|
||
using System.Collections;
|
||
|
||
/// <summary>
|
||
/// UI管理器 - 支持页面、弹窗和常驻UI的统一管理
|
||
/// 新增功能:常驻UI管理、弹窗UI管理、UI组管理、启动配置、状态持久化
|
||
/// WebGL兼容版本 - 使用Resources目录加载配置
|
||
/// </summary>
|
||
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<string, UIBase> uiDict = new Dictionary<string, UIBase>();
|
||
private Dictionary<string, bool> fixedUIStates = new Dictionary<string, bool>(); // 常驻UI状态记录
|
||
private Dictionary<string, bool> popupUIStates = new Dictionary<string, bool>(); // 弹窗UI状态记录
|
||
private Dictionary<string, bool> pageUIStates = new Dictionary<string, bool>(); // 页面UI状态记录
|
||
|
||
// 配置数据
|
||
private UIConfigData uiConfig;
|
||
|
||
// 弹窗管理
|
||
private List<string> activePopups = new List<string>(); // 当前活跃的弹窗
|
||
private Dictionary<string, Coroutine> autoHideCoroutines = new Dictionary<string, Coroutine>(); // 自动隐藏协程
|
||
|
||
void Awake()
|
||
{
|
||
Instance = this;
|
||
InitializeUIManager();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 初始化UI管理器
|
||
/// </summary>
|
||
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<GameObject>($"UI/{uiName}");
|
||
if (prefab == null)
|
||
{
|
||
Debug.LogError($"UI预制体未找到: {uiName}");
|
||
return;
|
||
}
|
||
|
||
// 实例化UI
|
||
GameObject go = Instantiate(prefab, parent);
|
||
ui = go.GetComponent<UIBase>();
|
||
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}");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 隐藏其他页面(不包括指定的页面)
|
||
/// </summary>
|
||
/// <param name="excludeUIName">要排除的UI名称</param>
|
||
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("其他页面已隐藏,状态已保存");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 隐藏所有页面(包括指定的页面)
|
||
/// </summary>
|
||
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管理功能
|
||
|
||
/// <summary>
|
||
/// 显示常驻UI
|
||
/// </summary>
|
||
/// <param name="uiName">UI名称</param>
|
||
/// <param name="param">参数</param>
|
||
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}");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 隐藏常驻UI
|
||
/// </summary>
|
||
/// <param name="uiName">UI名称</param>
|
||
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}");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 切换常驻UI显示状态
|
||
/// </summary>
|
||
/// <param name="uiName">UI名称</param>
|
||
public void ToggleFixedUI(string uiName)
|
||
{
|
||
if (IsFixedUIVisible(uiName))
|
||
{
|
||
HideFixedUI(uiName);
|
||
}
|
||
else
|
||
{
|
||
ShowFixedUI(uiName);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 检查常驻UI是否可见
|
||
/// </summary>
|
||
/// <param name="uiName">UI名称</param>
|
||
/// <returns>是否可见</returns>
|
||
public bool IsFixedUIVisible(string uiName)
|
||
{
|
||
return fixedUIStates.TryGetValue(uiName, out bool isVisible) && isVisible;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取所有常驻UI状态
|
||
/// </summary>
|
||
/// <returns>UI状态字典</returns>
|
||
public Dictionary<string, bool> GetAllFixedUIStates()
|
||
{
|
||
return new Dictionary<string, bool>(fixedUIStates);
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region 新增:弹窗UI管理功能
|
||
|
||
/// <summary>
|
||
/// 显示弹窗UI(带自动隐藏)
|
||
/// </summary>
|
||
/// <param name="uiName">UI名称</param>
|
||
/// <param name="param">参数</param>
|
||
/// <param name="autoHide">是否自动隐藏</param>
|
||
/// <param name="autoHideDelay">自动隐藏延迟</param>
|
||
public void ShowPopupWithAutoHide(string uiName, object param = null, bool autoHide = false, float autoHideDelay = 3.0f)
|
||
{
|
||
ShowPopup(uiName, param);
|
||
|
||
if (autoHide)
|
||
{
|
||
StartAutoHideCoroutine(uiName, autoHideDelay);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 隐藏弹窗UI
|
||
/// </summary>
|
||
/// <param name="uiName">UI名称</param>
|
||
public void HidePopup(string uiName)
|
||
{
|
||
HideUI(uiName);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 隐藏所有弹窗
|
||
/// </summary>
|
||
public void HideAllPopups()
|
||
{
|
||
foreach (var popupName in new List<string>(activePopups))
|
||
{
|
||
HidePopup(popupName);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取当前活跃弹窗数量
|
||
/// </summary>
|
||
/// <returns>活跃弹窗数量</returns>
|
||
public int GetActivePopupCount()
|
||
{
|
||
return activePopups.Count;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 检查弹窗是否可见
|
||
/// </summary>
|
||
/// <param name="uiName">UI名称</param>
|
||
/// <returns>是否可见</returns>
|
||
public bool IsPopupVisible(string uiName)
|
||
{
|
||
return popupUIStates.TryGetValue(uiName, out bool isVisible) && isVisible;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取所有弹窗UI状态
|
||
/// </summary>
|
||
/// <returns>弹窗状态字典</returns>
|
||
public Dictionary<string, bool> GetAllPopupUIStates()
|
||
{
|
||
return new Dictionary<string, bool>(popupUIStates);
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region 新增:UI组管理功能
|
||
|
||
/// <summary>
|
||
/// 显示UI组
|
||
/// </summary>
|
||
/// <param name="groupName">组名称</param>
|
||
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}");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 隐藏UI组
|
||
/// </summary>
|
||
/// <param name="groupName">组名称</param>
|
||
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}");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 切换UI组显示状态
|
||
/// </summary>
|
||
/// <param name="groupName">组名称</param>
|
||
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);
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 检查UI组是否可见
|
||
/// </summary>
|
||
/// <param name="groupName">组名称</param>
|
||
/// <returns>是否可见</returns>
|
||
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 新增:启动序列管理
|
||
|
||
/// <summary>
|
||
/// 执行启动序列
|
||
/// </summary>
|
||
public void ExecuteStartupSequence()
|
||
{
|
||
if (uiConfig?.startupSequence == null) return;
|
||
|
||
StartCoroutine(StartupSequenceCoroutine());
|
||
}
|
||
|
||
/// <summary>
|
||
/// 启动序列协程
|
||
/// </summary>
|
||
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("启动序列执行完成");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 根据名称显示UI(自动判断类型)
|
||
/// </summary>
|
||
/// <param name="uiName">UI名称</param>
|
||
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配置系统
|
||
|
||
/// <summary>
|
||
/// 加载UI配置
|
||
/// </summary>
|
||
private void LoadUIConfig()
|
||
{
|
||
try
|
||
{
|
||
// 从Resources目录加载配置文件
|
||
TextAsset configAsset = Resources.Load<TextAsset>(configResourcePath);
|
||
if (configAsset != null)
|
||
{
|
||
uiConfig = JsonUtility.FromJson<UIConfigData>(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}");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 应用启动配置
|
||
/// </summary>
|
||
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启动配置应用完成");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 预加载常驻UI(不显示)
|
||
/// </summary>
|
||
/// <param name="uiName">UI名称</param>
|
||
private void PreloadFixedUI(string uiName)
|
||
{
|
||
if (fixedRoot == null) return;
|
||
|
||
GameObject prefab = Resources.Load<GameObject>($"UI/{uiName}");
|
||
if (prefab != null)
|
||
{
|
||
GameObject go = Instantiate(prefab, fixedRoot);
|
||
UIBase ui = go.GetComponent<UIBase>();
|
||
if (ui != null)
|
||
{
|
||
uiDict[uiName] = ui;
|
||
go.SetActive(false); // 默认隐藏
|
||
fixedUIStates[uiName] = false;
|
||
Debug.Log($"常驻UI已预加载: {uiName}");
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 重新加载UI配置
|
||
/// </summary>
|
||
public void ReloadUIConfig()
|
||
{
|
||
LoadUIConfig();
|
||
Debug.Log("UI配置已重新加载");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取当前配置信息
|
||
/// </summary>
|
||
/// <returns>配置信息字符串</returns>
|
||
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 新增:状态持久化
|
||
|
||
/// <summary>
|
||
/// 保存常驻UI状态
|
||
/// </summary>
|
||
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}");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 保存弹窗UI状态
|
||
/// </summary>
|
||
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}");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 保存页面UI状态
|
||
/// </summary>
|
||
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}");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 加载常驻UI状态
|
||
/// </summary>
|
||
private void LoadFixedUIStates()
|
||
{
|
||
try
|
||
{
|
||
if (PlayerPrefs.HasKey("FixedUIStates"))
|
||
{
|
||
string statesJson = PlayerPrefs.GetString("FixedUIStates");
|
||
var statesData = JsonUtility.FromJson<FixedUIStates>(statesJson);
|
||
fixedUIStates = statesData.states;
|
||
Debug.Log("UI状态已从PlayerPrefs加载");
|
||
}
|
||
}
|
||
catch (Exception e)
|
||
{
|
||
Debug.LogError($"加载UI状态失败: {e.Message}");
|
||
fixedUIStates = new Dictionary<string, bool>();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 重置所有UI状态
|
||
/// </summary>
|
||
public void ResetAllUIStates()
|
||
{
|
||
fixedUIStates.Clear();
|
||
popupUIStates.Clear();
|
||
pageUIStates.Clear();
|
||
|
||
PlayerPrefs.DeleteKey("FixedUIStates");
|
||
PlayerPrefs.DeleteKey("PopupUIStates");
|
||
PlayerPrefs.DeleteKey("PageUIStates");
|
||
PlayerPrefs.Save();
|
||
|
||
Debug.Log("所有UI状态已重置");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 清除所有数据
|
||
/// </summary>
|
||
public void ClearAllData()
|
||
{
|
||
fixedUIStates.Clear();
|
||
popupUIStates.Clear();
|
||
pageUIStates.Clear();
|
||
|
||
PlayerPrefs.DeleteKey("FixedUIStates");
|
||
PlayerPrefs.DeleteKey("PopupUIStates");
|
||
PlayerPrefs.DeleteKey("PageUIStates");
|
||
PlayerPrefs.Save();
|
||
|
||
Debug.Log("所有数据已清除");
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region 新增:弹窗自动隐藏管理
|
||
|
||
/// <summary>
|
||
/// 处理弹窗自动隐藏
|
||
/// </summary>
|
||
/// <param name="uiName">UI名称</param>
|
||
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);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 开始自动隐藏协程
|
||
/// </summary>
|
||
/// <param name="uiName">UI名称</param>
|
||
/// <param name="delay">延迟时间</param>
|
||
private void StartAutoHideCoroutine(string uiName, float delay)
|
||
{
|
||
StopAutoHideCoroutine(uiName);
|
||
|
||
var coroutine = StartCoroutine(AutoHideCoroutine(uiName, delay));
|
||
autoHideCoroutines[uiName] = coroutine;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 停止自动隐藏协程
|
||
/// </summary>
|
||
/// <param name="uiName">UI名称</param>
|
||
private void StopAutoHideCoroutine(string uiName)
|
||
{
|
||
if (autoHideCoroutines.TryGetValue(uiName, out Coroutine coroutine))
|
||
{
|
||
StopCoroutine(coroutine);
|
||
autoHideCoroutines.Remove(uiName);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 自动隐藏协程
|
||
/// </summary>
|
||
/// <param name="uiName">UI名称</param>
|
||
/// <param name="delay">延迟时间</param>
|
||
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类型判断
|
||
|
||
/// <summary>
|
||
/// 判断是否为常驻UI
|
||
/// </summary>
|
||
/// <param name="uiName">UI名称</param>
|
||
/// <returns>是否为常驻UI</returns>
|
||
private bool IsFixedUI(string uiName)
|
||
{
|
||
return uiConfig?.fixedUIs?.Find(u => u.uiName == uiName) != null;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 判断是否为弹窗UI
|
||
/// </summary>
|
||
/// <param name="uiName">UI名称</param>
|
||
/// <returns>是否为弹窗UI</returns>
|
||
private bool IsPopupUI(string uiName)
|
||
{
|
||
return uiConfig?.popupUIs?.Find(u => u.uiName == uiName) != null;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 判断是否为页面UI
|
||
/// </summary>
|
||
/// <param name="uiName">UI名称</param>
|
||
/// <returns>是否为页面UI</returns>
|
||
private bool IsPageUI(string uiName)
|
||
{
|
||
return uiConfig?.pageUIs?.Find(u => u.uiName == uiName) != null;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 检查UI是否可见
|
||
/// </summary>
|
||
/// <param name="uiName">UI名称</param>
|
||
/// <returns>是否可见</returns>
|
||
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
|
||
|
||
/// <summary>
|
||
/// 重置页面UI状态
|
||
/// </summary>
|
||
/// <param name="uiName">UI名称</param>
|
||
public void ResetPageUIState(string uiName)
|
||
{
|
||
if (pageUIStates.ContainsKey(uiName))
|
||
{
|
||
pageUIStates[uiName] = false;
|
||
SavePageUIStates();
|
||
Debug.Log($"页面UI状态已重置: {uiName} = false");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 重置所有页面UI状态
|
||
/// </summary>
|
||
public void ResetAllPageUIStates()
|
||
{
|
||
pageUIStates.Clear();
|
||
SavePageUIStates();
|
||
Debug.Log("所有页面UI状态已重置");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 强制显示页面(忽略状态检查,直接显示)
|
||
/// </summary>
|
||
/// <param name="uiName">UI名称</param>
|
||
/// <param name="param">参数</param>
|
||
public void ForceShowPage(string uiName, object param = null)
|
||
{
|
||
Debug.Log($"强制显示页面: {uiName}");
|
||
|
||
// 直接显示,不调用HideOtherPages
|
||
ShowUI(uiName, pageRoot, param);
|
||
|
||
// 强制设置状态为可见
|
||
pageUIStates[uiName] = true;
|
||
SavePageUIStates();
|
||
|
||
Debug.Log($"页面已强制显示: {uiName}");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 安全显示页面(检查状态,避免重复显示)
|
||
/// </summary>
|
||
/// <param name="uiName">UI名称</param>
|
||
/// <param name="param">参数</param>
|
||
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}");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 检查页面UI是否可见
|
||
/// </summary>
|
||
/// <param name="uiName">UI名称</param>
|
||
/// <returns>是否可见</returns>
|
||
public bool IsPageVisible(string uiName)
|
||
{
|
||
return pageUIStates.TryGetValue(uiName, out bool isVisible) && isVisible;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取所有页面UI状态
|
||
/// </summary>
|
||
/// <returns>页面状态字典</returns>
|
||
public Dictionary<string, bool> GetAllPageUIStates()
|
||
{
|
||
return new Dictionary<string, bool>(pageUIStates);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 调试:打印当前所有UI状态
|
||
/// </summary>
|
||
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("==================");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取UI管理器状态信息
|
||
/// </summary>
|
||
/// <returns>状态信息字符串</returns>
|
||
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 配置数据结构
|
||
|
||
/// <summary>
|
||
/// UI配置数据
|
||
/// </summary>
|
||
[Serializable]
|
||
public class UIConfigData
|
||
{
|
||
public List<FixedUIConfig> fixedUIs = new List<FixedUIConfig>();
|
||
public List<PopupUIConfig> popupUIs = new List<PopupUIConfig>();
|
||
public List<PageUIConfig> pageUIs = new List<PageUIConfig>();
|
||
public List<UIGroupConfig> uiGroups = new List<UIGroupConfig>();
|
||
public List<StartupStepConfig> startupSequence = new List<StartupStepConfig>();
|
||
public DefaultSettingsConfig defaultSettings = new DefaultSettingsConfig();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 常驻UI配置
|
||
/// </summary>
|
||
[Serializable]
|
||
public class FixedUIConfig
|
||
{
|
||
public string uiName; // UI名称
|
||
public bool visibleOnStart; // 启动时是否可见
|
||
public string description; // 描述
|
||
}
|
||
|
||
/// <summary>
|
||
/// 弹窗UI配置
|
||
/// </summary>
|
||
[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; // 描述
|
||
}
|
||
|
||
/// <summary>
|
||
/// 页面UI配置
|
||
/// </summary>
|
||
[Serializable]
|
||
public class PageUIConfig
|
||
{
|
||
public string uiName; // UI名称
|
||
public bool visibleOnStart; // 启动时是否可见
|
||
public bool canStack; // 是否可以叠加
|
||
public string description; // 描述
|
||
}
|
||
|
||
/// <summary>
|
||
/// UI组配置
|
||
/// </summary>
|
||
[Serializable]
|
||
public class UIGroupConfig
|
||
{
|
||
public string groupName; // 组名称
|
||
public List<string> uis; // UI名称列表
|
||
public bool visibleOnStart; // 启动时是否可见
|
||
public string description; // 描述
|
||
}
|
||
|
||
/// <summary>
|
||
/// 启动步骤配置
|
||
/// </summary>
|
||
[Serializable]
|
||
public class StartupStepConfig
|
||
{
|
||
public int step; // 步骤序号
|
||
public string action; // 动作类型
|
||
public string uiName; // UI名称
|
||
public string groupName; // 组名称
|
||
public float delay; // 延迟时间
|
||
public string description; // 描述
|
||
}
|
||
|
||
/// <summary>
|
||
/// 默认设置配置
|
||
/// </summary>
|
||
[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; // 默认弹窗层级
|
||
}
|
||
|
||
/// <summary>
|
||
/// 常驻UI状态数据
|
||
/// </summary>
|
||
[Serializable]
|
||
public class FixedUIStates
|
||
{
|
||
public Dictionary<string, bool> states = new Dictionary<string, bool>();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 弹窗UI状态数据
|
||
/// </summary>
|
||
[Serializable]
|
||
public class PopupUIStates
|
||
{
|
||
public Dictionary<string, bool> states = new Dictionary<string, bool>();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 页面UI状态数据
|
||
/// </summary>
|
||
[Serializable]
|
||
public class PageUIStates
|
||
{
|
||
public Dictionary<string, bool> states = new Dictionary<string, bool>();
|
||
}
|
||
|
||
#endregion |