当前位置: 首页 > news >正文

unity UI管理器

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;

// UI界面基类
public abstract class UIBase : MonoBehaviour
{
    [Header("UI Settings")]
    public bool keepInStack = true; // 是否保留在界面栈中
    public bool destroyWhenClose = false; // 关闭时是否销毁

    // 界面打开关闭事件
    public UnityEvent onOpen;
    public UnityEvent onClose;

    // 界面初始化
    public virtual void Init() { }

    // 界面打开
    // 在UIBase中添加
    public virtual void Open()
    {
        Debug.Log($"Opening {gameObject.name}");
        gameObject.SetActive(true);
        onOpen?.Invoke();
    }

    public virtual void Close()
    {
        Debug.Log($"Closing {gameObject.name}");
        gameObject.SetActive(false);
        onClose?.Invoke();

        if (destroyWhenClose)
        {
            Debug.Log($"Destroying {gameObject.name}");
            Destroy(gameObject);
        }
    }

    // 返回按钮处理(Android返回键或界面返回按钮)
    public virtual void OnBackPressed()
    {
        UIManager.Instance.CloseUI(this);
    }
}




// UI管理器
public class UIManager : MonoBehaviour
{
    private static UIManager _instance;
    public static UIManager Instance => _instance;

    [Header("UI Settings")]
    public Transform uiRoot; // UI根节点
    public GameObject loadingScreen; // 加载界面

    private Dictionary<string, GameObject> _uiPrefabs = new Dictionary<string, GameObject>();
    private Stack<UIBase> _uiStack = new Stack<UIBase>();
    private Dictionary<string, UIBase> _loadedUIs = new Dictionary<string, UIBase>();

    private void Awake()
    {
        if (_instance != null && _instance != this)
        {
            Destroy(gameObject);
            return;
        }

        _instance = this;
        DontDestroyOnLoad(gameObject);
    }

    // 注册UI预制体
    public void RegisterUI(string uiName, GameObject prefab)
    {
        if (!_uiPrefabs.ContainsKey(uiName))
        {
            _uiPrefabs.Add(uiName, prefab);
        }
    }

    // 同步打开UI
    public UIBase OpenUI(string uiName, object data = null)
    {
        if (loadingScreen != null) loadingScreen.SetActive(true);

        UIBase ui = GetOrCreateUI(uiName);
        if (ui == null)
        {
            Debug.LogError($"UI {uiName} not found!");
            if (loadingScreen != null) loadingScreen.SetActive(false);
            return null;
        }

        // 强制激活新UI
        ui.gameObject.SetActive(true);

        // 处理当前UI
        if (_uiStack.Count > 0)
        {
            var currentUI = _uiStack.Peek();

            // 无论keepInStack如何,都关闭当前UI
            currentUI.Close();

            // 如果新UI不保留栈或当前UI需要销毁
            if (!ui.keepInStack || currentUI.destroyWhenClose)
            {
                _uiStack.Pop();
                if (currentUI.destroyWhenClose)
                {
                    _loadedUIs.Remove(currentUI.gameObject.name);
                }
            }
        }

        // 初始化并打开新UI
        ui.Init();
        ui.Open();

        // 添加到栈(如果需要)
        if (ui.keepInStack)
        {
            _uiStack.Push(ui);
        }

        if (loadingScreen != null) loadingScreen.SetActive(false);

        Debug.Log($"当前栈内UI数量: {_uiStack.Count}");
        return ui;
    }

    // 异步打开UI
    public IEnumerator OpenUIAsync(string uiName, object data = null)
    {
        if (loadingScreen != null) loadingScreen.SetActive(true);

        yield return null; // 等待一帧

        UIBase ui = GetOrCreateUI(uiName);
        if (ui == null)
        {
            Debug.LogError($"UI {uiName} not found!");
            if (loadingScreen != null) loadingScreen.SetActive(false);
            yield break;
        }

        if (_uiStack.Count > 0 && !ui.keepInStack)
        {
            var currentUI = _uiStack.Peek();
            currentUI.Close();
        }

        ui.Init();
        ui.Open();

        if (ui.keepInStack)
        {
            _uiStack.Push(ui);
        }

        if (loadingScreen != null) loadingScreen.SetActive(false);
    }

    // 关闭UI
    public void CloseUI(UIBase ui)
    {
        if (ui == null) return;

        ui.Close();

        if (_uiStack.Count > 0 && _uiStack.Peek() == ui)
        {
            _uiStack.Pop();

            // 打开上一个UI
            if (_uiStack.Count > 0)
            {
                var prevUI = _uiStack.Peek();
                prevUI.Open();
            }
        }
    }

    // 关闭当前UI
    public void CloseCurrentUI()
    {
        if (_uiStack.Count > 0)
        {
            CloseUI(_uiStack.Peek());
        }
    }

    // 获取或创建UI
    private UIBase GetOrCreateUI(string uiName)
    {
        // 检查是否已加载
        if (_loadedUIs.TryGetValue(uiName, out UIBase loadedUI))
        {
            return loadedUI;
        }

        // 检查是否有预制体
        if (!_uiPrefabs.TryGetValue(uiName, out GameObject prefab))
        {
            Debug.LogError($"UI prefab {uiName} not registered!");
            return null;
        }

        // 实例化UI
        GameObject uiObj = Instantiate(prefab, uiRoot);
        UIBase ui = uiObj.GetComponent<UIBase>();
        if (ui == null)
        {
            Debug.LogError($"UI {uiName} has no UIBase component!");
            Destroy(uiObj);
            return null;
        }

        uiObj.name = uiName;
        _loadedUIs.Add(uiName, ui);

        return ui;
    }

    // 清空所有UI
    public void ClearAll()
    {
        while (_uiStack.Count > 0)
        {
            var ui = _uiStack.Pop();
            ui.Close();
            if (ui.destroyWhenClose)
            {
                _loadedUIs.Remove(ui.gameObject.name);
            }
        }
    }

    // 处理返回键
    private void Update()
    {
        if (Input.GetKeyDown(KeyCode.Escape))
        {
            if (_uiStack.Count > 0)
            {
                _uiStack.Peek().OnBackPressed();
            }
        }
    }
}

然后注册UI

using UnityEngine;

public class GameInitializer : MonoBehaviour
{
    [SerializeField] private GameObject LoginInterface;
    [SerializeField] private GameObject SingerOrMulti;
    [SerializeField] private GameObject ModuleSelect;
    [SerializeField] private GameObject SandTableSelect;
    [SerializeField] private GameObject DataReport;
    [SerializeField] private GameObject SettingInterface;
    private void Start()
    {
        // 注册UI预制体
        UIManager.Instance.RegisterUI("LoginInterface", LoginInterface);
        UIManager.Instance.RegisterUI("SingerOrMulti", SingerOrMulti);
        UIManager.Instance.RegisterUI("ModuleSelect", ModuleSelect);
        UIManager.Instance.RegisterUI("SandTableSelect", SandTableSelect);
        UIManager.Instance.RegisterUI("DataReport", DataReport);
        UIManager.Instance.RegisterUI("SettingInterface", SettingInterface);
        // 打开主菜单
        UIManager.Instance.OpenUI("LoginInterface");
    }
}

调用UI界面 是预制体
在这里插入图片描述
脚本要继承UIbase

相关文章:

  • 笔记:代码随想录算法训练营day64:拓扑排序精讲、dijkstra(朴素版)精讲
  • 算法设计学习3
  • HTTP,请求响应报头,以及抓包工具的讨论
  • go 使用os复制文件
  • ChatGPT 与 DeepSeek:学术科研的智能 “双引擎”
  • 经典卷积神经网络LeNet实现(pytorch版)
  • Unity3D依赖注入容器使用指南博毅创为博毅创为
  • Java接口(二)
  • dp4-ai 安装教程
  • 化繁为简解决leetcode第1289题下降路径最小和II
  • 深度解剖 TCP 三次握手 四次挥手
  • LXC 导入多Linux系统
  • mybatis-genertor(代码生成)源码及扩展笔记
  • stm32F103C8T6引脚定义
  • python 的gui开发示例
  • MySQL Online DDL:演变、原理与实践
  • RAG 文档嵌入到向量数据库FAISS
  • 前沿科技:具身智能(Embodied Intelligence)详解
  • 利用cusur+claude3.7 angent模式一句提示词生成一个前端网站
  • 阿里拟收购两氢一氧公司 陈航将出任阿里集团钉钉 CEO
  • 2025五一档新片电影总票房破亿
  • 中央网信办部署开展“清朗·整治AI技术滥用”专项行动
  • 为治理商家“卷款跑路”“退卡难”,预付式消费司法解释5月起实施
  • “即买即退”扩容提质,上海静安推出离境退税2.0版新政
  • 五一“拼假”催热超长假期,热门酒店民宿一房难求
  • 习近平对辽宁辽阳市白塔区一饭店火灾事故作出重要指示