Unity 简易UI管理器

这篇具有很好参考价值的文章主要介绍了Unity 简易UI管理器。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

首先我们需要先定义这么一个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事件的,这两者都是必须存在的.

Unity 简易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

 文章来源地址https://www.toymoban.com/news/detail-486514.html

到了这里,关于Unity 简易UI管理器的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • unity初学6——简易的UI制作(血条制作)和音频加入以及NPC的对话气泡(2d)

    该文来是学习chutianbo老师的笔记,链接b站 1.右键Hierarchy空白处 UI➡canvas 2.这里一共使用了三个素材 层级结构 UI:初始画布 characters:头像 Mask:遮罩层 healthbar:血条 这里我们先回到UI(也就是一开始创建的Canvas) 我们一开始有用的应该只有渲染模式render Mode,他有三种模式

    2023年04月08日
    浏览(39)
  • 数据结构与算法这么难,为什么我们还要学习?

    提到数据结构与算法,就一定会伴随着诸多所谓的坚持和抱怨。同时,还有两个词总是出现,一个是内功,是对知识的定位,一个是吃透,是对自己

    2024年01月19日
    浏览(54)
  • 过了这次我们就算成长了,以后不要再这么幼稚啦

    这句话是我提出离职刚一周 老板教训一些同事说的话。 这件事发生在我目前服役过最大的公司 连用科技 还是先从我们入职说起吧,我是去年二月八号面试 ,十号入职的连用科技。当时面试我的李总 说了一句比较真诚的话:“其实我看你之前做的东西,和各方面技术都不是特

    2024年02月03日
    浏览(39)
  • 【Unity3D】UI Toolkit自定义元素

    1 前言         UI Toolkit 支持通过继承 VisualElement 实现自定义元素,便于通过脚本控制元素。另外,UI Toolkit 也支持将一个容器及其所有子元素作为一个模板,便于通过脚本复制模板。         如果读者对 UI Toolkit 不是太了解,可以参考以下内容。 UI Toolkit简介 UI Toolkit容器

    2024年02月09日
    浏览(50)
  • 视频中为什么需要这么多的颜色空间?

    作者 | 17哥 导读 :在视频处理中,我们经常会用到不同的色彩空间: 非线性RGB,线性 RGB,YUV,XYZ ……为什么需要这么多的色彩空间呢?为什么在 FFMpeg 中会有 color_space,color_transfer,color_primaries 等一系列的颜色属性呢?这些术语之间究竟隐藏着什么秘密 ? 全文5840字,预计阅

    2023年04月13日
    浏览(42)
  • C++这么难,为什么我们还要用C++?C++ Core Guidelines解析给了我答案

    C++ 是一门强大而复杂的编程语言,它有其独特的应用场景和优势,尽管它可能在学习和使用上有一些挑战,但仍然被广泛采用的原因有很多,尽管 C++ 有其优势,但它也确实有一些复杂性和潜在的陷阱,因此在选择使用它时需要权衡。对于一些应用场景,其他编程语言,如Py

    2024年02月09日
    浏览(47)
  • Unity的UI管理器

    1、代码  2、如何使用 创建一个测试的UI面板(随便乱拼),将他作为预设体 创建一个测试类 启动发现已经动态创建了Canvas和对应面板

    2024年02月09日
    浏览(32)
  • Unity组件开发--UI管理器

    1.Canvas组件: 注意属性: (1)渲染模式是:屏幕空间相机 (2)创建一个UICamera节点,管理相机 (3)屏幕画布缩放模式 (4)画布下挂载两个脚本:UIRoot和UIManager (5)事件系统管理节点必须有: 2.画布下其他节点类型:用于不同界面类型的管理归类window类型 3.先看UIRoot脚本

    2024年01月16日
    浏览(31)
  • Unity 3D 开发--UI管理框架

    一、UI基类 一般情况下都是用Panel做容器来放各种控件的,一个Panle相当一个UI小界面,然后做成Prefab进行加载,所有界面都有载入载出功能,有的可能还有等待和恢复的,适合建立一个UI基类,然后各个子界面继承。 二、UI子类 每个UI子界面都继承基类,然后实现各个方法,

    2024年02月13日
    浏览(45)
  • Unity UI -- (3)管理屏幕大小和锚点

            在前面我们探索了一些基本的文本格式。我们需要考虑一个问题,这个文本在屏幕大小发生变化时该如何适应呢?         在Unity中,我们可以使用Canvas和Anchor Point(锚点)系统来确保UI元素总是出现在正确的位置,不管它们在哪种屏幕上出现。         在编辑修改

    2024年02月11日
    浏览(38)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包