Unity 简易UI管理器

news2024/11/15 21:20:42

首先我们需要先定义这么一个UIManager类。

public class UIManager
{

}
UI管理器嘛,顾名思义肯定是用来管理我们游戏中的UI的,而我们游戏当中的UI呢一般是以面板为单位来进行划分的。所以我们还需要一个UI面板类。然后通过我们的UI管理器来管理我们的UI面板。

public class UIPanel
{

}
那么我们在UI管理器当中呢使用字典去管理我们的UI面板。

public class UIManager
{
    Dictionary<string, UIPanel> panelsDic;
    public UIManager()
    {
        panelsDic = new Dictionary<string, UIPanel>();
    }
}
那么我们的UI面板当中有几个最基本的属性

比如最基本的声明周期函数,OnShow,OnHide,当面板被打开和隐藏时去执行的函数。以及这个面板所对应的预制体的资源路径或名称。

public abstract class UIPanel
{
    private string path;
    public string Path { get { return path; } }

    public GameObject root;

    public abstract void OnShow();

    public abstract void OnHide();

    public UIPanel(string path)
    {
        this.path = path;
    }

}
首先呢这个面板类是一个抽象类,我们的登录面板或者注册面板等等的UI面板都需要去继承他,所以这个面板类本身是不应该可以实例化的,因此是一个抽象类,然后是path,也就是这个UI面板所对应的预制体的资源路径,当我们通过UI管理器去打开这个面板的时候需要根据这个路径去加载面板资源并拿到这个资源的引用然后赋值给root,也就是这个预制体的根节点,然后我们这个脚本才可以去对这个物体进行操作.然后在打开和隐藏的时候我们会分别去调用OnShow和OnHide方法,而这两个方法则是有子类去书写具体实现的.

那么接下来我们来写UIManager.

public class UIManager
{
    Transform canvas;
    Dictionary<string, UIPanel> panelsDic;
    public UIManager()
    {
        canvas = GameObject.Find("Canvas").transform;
        GameObject eventSystem = GameObject.Find("EventSystem");
        GameObject.DontDestroyOnLoad(canvas);
        GameObject.DontDestroyOnLoad(eventSystem);
        panelsDic = new Dictionary<string, UIPanel>();
    }
}
刚才说了,我们使用一个字典来存储所有的UI面板.

然后我们还应该在unity界面创建一个Canvas和EventSystem,这两个物体,前者是所有UI面板的父节点,后者是检测UI事件的,这两者都是必须存在的.

然后还应该将这两个物体都设置为不被销毁的,以防止在切换场景的时候被销毁掉.

然后我们还应该提供打开面板和关闭面板两个最基本的操作.

public class UIManager
{
    Transform canvas;
    Dictionary<string, UIPanel> panelsDic;
    public UIManager()
    {
        canvas = GameObject.Find("Canvas").transform;
        GameObject eventSystem = GameObject.Find("EventSystem");
        GameObject.DontDestroyOnLoad(canvas);
        GameObject.DontDestroyOnLoad(eventSystem);
        panelsDic = new Dictionary<string, UIPanel>();
    }

    public void OpenPanel<T>(T panel) where T : UIPanel
    {

    }

    public void ClosePanel<T>(T panel) where T : UIPanel
    {

    }
}
在这里我们对关闭和打开面板都提供一个泛型接口,传递面板传递进来,但是我们如果每次都要将这个面板对象都传进来就太麻烦了,所以我们再次对面板类进行扩展.

public abstract class UIPanel
{
    private string path;
    public string Path { get { return path; } }

    public GameObject root;

    public abstract void OnShow();

    public abstract void OnHide();

    public void OpenPanel() => Singleton<UIManager>.Instance.OpenPanel(this);

    public void ClosePanel() => Singleton<UIManager>.Instance.ClosePanel(this);

    public UIPanel(string path)
    {
        this.path = path;
    }

}
那么这时候我们就不需要通过UI管理器去打开或者隐藏面板了,而是直接调用这个对象的方法.

接下来讲一下这两个方法的具体实现.

public class UIManager
{
    Transform canvas;
    Dictionary<string, UIPanel> panelsDic;
    public UIManager()
    {
        canvas = GameObject.Find("Canvas").transform;
        GameObject eventSystem = GameObject.Find("EventSystem");
        GameObject.DontDestroyOnLoad(canvas);
        GameObject.DontDestroyOnLoad(eventSystem);
        panelsDic = new Dictionary<string, UIPanel>();
    }

    public void OpenPanel<T>(T panel) where T : UIPanel
    {
        if(panelsDic.TryGetValue(typeof(T).Name,out UIPanel oldPanel))
        {
            oldPanel.root.SetActive(true);
            oldPanel.OnShow();
        }
        else
        {
            GameObject newGO = Singleton<ResourcesManager>.Instance.Load<GameObject>(panel.Path);
            panel.root = newGO;
            panel.root.name = panel.Path;
            panel.OnShow();
            newGO.transform.SetParent(canvas);
            panelsDic.Add(typeof(T).Name,panel);
        }
    }

    public void ClosePanel<T>(T panel) where T : UIPanel
    {
        if(panelsDic.TryGetValue(typeof(T).Name,out UIPanel oldPanel))
        {
            oldPanel.root.SetActive(false);
        }
    }

}
其实很简单,打开面板我们这里的实现是先检查字典当中是否存在该面板,如果存在就直接显示出来,并且调用他的OnShow方法,如果不存在,则从资源管理器中去加载这个资源,然后调用他的OnShow方法.关闭就更简单了,判断是否存在于该字典当中,存在的话就隐藏,不存在的话,.....那就是逻辑有问题了,因为我们每次打开都是有添加进字典的,这里可以捕捉下错误.也许是误操作.

最后我在把这整个的代码完整的发一下,因为用到了前两篇的内容.

public class Singleton<T> where T : new()
{
    static T instance;
    public static T Instance
    {
        get
        {
            if (instance == null)
                instance = new T();
            return instance;
        }
    }
}


public class ResourcesManager
{
    private Dictionary<string, IResource> ressDic;
    public ResourcesManager()
{
        ressDic = new Dictionary<string, IResource>();
    }

    public T Load<T>(string path) where T : UnityEngine.Object
    {
        if (ressDic.TryGetValue(path, out IResource iRes))
            return (iRes as Resource<T>).Res;
        T res = Resources.Load<T>(path);
        ressDic.Add(path, new Resource<T>(path, res));
        return res;
    }
}


public interface IResource
{

}

public class Resource<T> : IResource
{
    public Resource(string path, T res)
{
        this.path = path;
        this.res = res;
    }

    private string path;
    private T res;
    public string Path { get; }
    public T Res { get; }
}

public class UIManager
{
    Transform canvas;
    Dictionary<string, UIPanel> panelsDic;
    public UIManager()
{
        canvas = GameObject.Find("Canvas").transform;
        GameObject eventSystem = GameObject.Find("EventSystem");
        GameObject.DontDestroyOnLoad(canvas);
        GameObject.DontDestroyOnLoad(eventSystem);
        panelsDic = new Dictionary<string, UIPanel>();
    }

    public void OpenPanel<T>(T panel) where T : UIPanel
    {
        if(panelsDic.TryGetValue(typeof(T).Name,out UIPanel oldPanel))
        {
            oldPanel.root.SetActive(true);
            oldPanel.OnShow();
        }
        else
        {
            GameObject newGO = Singleton<ResourcesManager>.Instance.Load<GameObject>(panel.Path);
            panel.root = newGO;
            panel.root.name = panel.Path;
            panel.OnShow();
            newGO.transform.SetParent(canvas);
            panelsDic.Add(typeof(T).Name,panel);
        }
    }

    public void ClosePanel<T>(T panel) where T : UIPanel
    {
        if(panelsDic.TryGetValue(typeof(T).Name,out UIPanel oldPanel))
        {
            oldPanel.root.SetActive(false);
        }
    }

}

public abstract class UIPanel
{
    private string path;
    public string Path { get { return path; } }

    public GameObject root;

    public abstract void OnShow();

    public abstract void OnHide();

    public void OpenPanel() => Singleton<UIManager>.Instance.OpenPanel(this);

    public void ClosePanel() => Singleton<UIManager>.Instance.ClosePanel(this);

    public UIPanel(string path)
{
        this.path = path;
    }

}
 作者:引擎猫 https://www.bilibili.com/read/cv12007091?spm_id_from=333.999.0.0 出处:bilibili

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/635126.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux——创建容器并将本地调试完全的前后端分离项目打包上传docker运行

前言 在上传之前需要有一个已经搭建好的前后端分离的项目&#xff0c;下面是后端的项目结构图和前端页面图 在服务器上利用准备好的docker镜像配置一个新的容器 创建容器 这里使用的docker镜像的OS是ubuntu20.04.需要自备。 注意好端口映射: 通常前端项目使用的端口号一般都…

【DeepSpeed 教程翻译】二,Megatron-LM GPT2,Zero Redundancy Optimizer 和 ZeRO-Offload

文章目录 0x0. 前言0x1. Megatron-LM GPT2使用原始的 Megatron-LM 训练 GPT2设置训练数据运行未修改的Megatron-LM GPT2模型开启DeepSpeed参数解析初始化和训练初始化使用训练API前向传播 反向传播更新模型参数损失缩放检查点保存和加载 DeepSpeed Activation Checkpoints&…

异常检测学习笔记 三、线性回归方法、主成分分析、支持向量机

一、线性回归方法 类似这样的函数是线性回归模型和支持向量机的基础,线性函数很简单,如果原始问题是非线性的,那么将其转化为线性问题更容易处理,比如下面的方程。 线性映射是主成分分析的重要组成部分。 寻找响应(因变量)和解释变量(自变量)之间的线性关系,…

python实现图片、gif转为字符样式图与gif,pyqt5、opencv、PIL

使用pyqt5将图片转换为字符样式的图片步骤如下&#xff1a; 设计pyqt5界面&#xff0c;使用Qt Designer 设计界面样式 将ui文件转换为py代码 书写相关按钮信号槽代码打开图片按钮需要一下逻辑步骤弹出选择路径的界面来选择文件保存 图片的路径&#xff0c;能在转换保存的按钮…

数字IC前端学习笔记:FIFO的Verilog实现(二)

相关文章 数字IC前端学习笔记&#xff1a;LSFR&#xff08;线性反馈移位寄存器&#xff09; 数字IC前端学习笔记&#xff1a;跨时钟域信号同步 数字IC前端学习笔记&#xff1a;信号同步和边沿检测 数字IC前端学习笔记&#xff1a;锁存器Latch的综合 数字IC前端学习笔记&am…

最新站长必备在线工具箱系统源码 含上百款工具 带后台版本

&#x1f388; 限时活动领体验会员&#xff1a;可下载程序网创项目短视频素材 &#x1f388; 最新站长必备在线工具箱系统源码 含上百款工具 带后台版本 自适应模板 优化修复版 系统一切正常可用&#xff0c;后台登录方式是QQ扫码登录的,建议有能力的可以改一改 此工具箱系统…

【LVS + Keepalived 群集】

目录 一、Keepalived 案列分析二、Keeoalived 工具介绍1、keepalived 实现原理剖析2、VRRP &#xff08;虚拟路由冗余协议&#xff09;是指对路由器的一种备份解决方案3、keepalived 案例讲解4、keepalived 的安装与启动5、Keepalived及其工作原理Keepalived体系主要模块及其作…

SQL锁总结

一、概述 介绍 锁是计算机协调多个进程或线程并发访问某一资源的机制。在数据库中&#xff0c;除传统的计算资源(CPU、RAM、I/O)的争用以外&#xff0c;数据也是一种供许多用户共享的资源。如何保证数据并发访问的一致性、有效性是所有数据库必须解决的一个问题&#xff0c;锁…

springboot3嵌入式容器源码解析

问题分析 不同于使用springmvc,在我们使用springboot时无需配置tomcat就可以直接使用&#xff0c;这就说明springboot已经在我们启动项目时将tomcat配置好了&#xff0c;接下来我们就来看看springboot底层是怎么实现的。 源码解析 ServletWebServerFactoryAutoConfiguratio…

【Python爬虫】整站40万条房价数据并行抓取,可更换抓取城市

目录 前言一、获取索引一级位置&#xff1a;区域信息二级位置&#xff1a;板块信息三级位置&#xff1a;地铁信息&#xff08;搜索地铁周边房源信息&#xff09; 二、获取索引页最大页数三、抓取房源信息Tag四、分配任务&#xff0c;并行抓取五、将抓取结果存储到excel中&#…

go map源码探索(查找、插入、删除、扩容、遍历)

文章目录 概要一、Go map结构二、Go map初始化2.1、不带容量初始化2.2、带容量初始化 三、Go map查找四、Go map插入4.1、插入源码分析4.2、溢出桶申请策略 五、删除源码分析六、扩容与迁移源码分析6.1、扩容条件6.1.1、当前负载因子大于6.56.1.2、有过多的溢出桶 6.2、扩容6.3…

LVS+Keepalivedd

Keepalived 一、Keepalived及其工作原理二、实验非抢占模式的设置 三、脑裂现象四、Nginx高可用模式 一、Keepalived及其工作原理 keepalived是一个基于VRRP协议来实现的LVS服务高可用方案&#xff0c;可用解决静态路由出现的单点故障问题。 在一个LVS服务集群中通常有主服务器…

11.枚举和注解|Java学习笔记

文章目录 枚举 enumeration enum自定义实现枚举自定义类实现枚举总结 使用enum关键字实现枚举实现方法Enum类方法enum实现接口 注解注解的理解JDK的元Annotation&#xff08;元注解&#xff09; 枚举 enumeration enum 从一个需求引入&#xff1a; 要求创建季节(Season) 对象&…

matlab 使用预训练神经网络和SVM进行苹果分级(带图形界面)支持其他物品图片分级或者分类

目录 数据集&#xff1a; 实验代码&#xff1a;alexnet版 如果你的matlab不是正版&#xff0c;先看这里&#xff1a; 数据集结构&#xff1a; 训练代码&#xff1a; 训练结果&#xff1a; 图形界面&#xff1a; 界面展示&#xff1a; 其他&#xff1a; 输出结果: 实验…

代码规范

一 、代码规范 程序员写代码&#xff0c;不仅仅是实现功能 1. 名称 在Python开发过程中会创建文件夹/文件/变量等&#xff0c;这些在命名有一些潜规则&#xff08;编写代码时也要注意pep8规范&#xff09;。 文件夹&#xff0c;小写 & 小写下划线连接&#xff0c;例如&a…

jmeter 在linux服务器中执行性能测试、监听服务器资源指标

jmeter监控服务器资源 资源准备jmeter安装&#xff08;Windows 版&#xff09;jmeter安装&#xff08;linux 版&#xff09;ServerAgent安装&#xff08;linux 版&#xff09;配置脚本并执行测试 资源准备 下载apache-jmeter-5.5文件;下载ServerAgent-2.2.3文件; jmeter安装&…

ZooKeeper的集群部署和启动与关闭

ZooKeeper是一个分布式应用程序协调服务。一个ZooKeeper集群可以存在多个Follower和Observer服务器&#xff0c;但只允许存在一台Leader服务器。如果Leader服务器宕机&#xff0c;那么ZooKeeper集群的其它服务器会投票选举出一个新的Leader服务器&#xff0c;为防止投票数不过半…

2023最新社交圈子即时聊天通信小程序+前端UNIAPP

&#x1f388; 限时活动领体验会员&#xff1a;可下载程序网创项目短视频素材 &#x1f388; &#x1f389; 有需要的朋友记得关赞评&#xff0c;阅读文章底部来交流&#xff01;&#xff01;&#xff01; &#x1f389; ✨ 源码介绍 2023最新多端社交圈子系统源码 | 陌生人社交…

[openeuler]Yocto embedded 联合sig例会 (2022-12-15)

Yocto & embedded 联合sig例会 (2022-12-15)_哔哩哔哩_bilibili

【C/C++】详解 函数重载和应用

创作不易&#xff0c;本篇文章如果帮助到了你&#xff0c;还请点赞 关注支持一下♡>&#x16966;<)!! 主页专栏有更多知识&#xff0c;如有疑问欢迎大家指正讨论&#xff0c;共同进步&#xff01; &#x1f525;c系列专栏&#xff1a;C/C零基础到精通 &#x1f525; 给大…