UnityVR--UIManager--UI管理1

目录

前言

UI节点的结构

需要用到的组件

  1. CanvasGroup

  2. Button等控件的OnClick()监听

  3. EventTrigger

建立UI工具集

  1. 管理UI节点

  2.  UIBase包含了以下的工具

建立分面板的管理工具——以主面板MainUi为例


前言

  UI在项目中的重要性不言而喻,并且UI控件的种类繁多(UGUI简单介绍仅仅列举了常用控件和重要参数),不仅需要有一个统一的工具管理器来控制各个UI节点的初始化、排列、 组件等,还需要有一个UIManager在项目中统一控制。

  本篇主要介绍UI的工具集UITools,由于篇幅有限,UIManager放在下一篇。

  UITools提供了一系列的关于UI节点的操作工具,尤其是对于Button、Slider等交互性较强的UI控件来说,集中管理这些工具会使代码重用性大大提高,减少系统消耗。

  先从场景中的UI节点设置开始:

UI节点的结构

  UI面板的结构大致如下图,不同的面板使用Canvas作为载体,在场景显示中,先加载的节点(上面的节点)先显示,后加载的节点覆盖在最上面:

  比如,点击主界面中的Play按钮,显示其中一个EXTRAS面板,这个面板就要放在主面板节点的下面,显示时覆盖在主面板上。

  *注:在不少项目中,场景中没有任何UI节点,而UI都是作为预制体的形式存在于Resource资源文件夹中,如下图,制作成UI预制体放在Resource/UI文件夹内(这里用的例子是从AssetStore下载的,只保留了最基本的几个面板):

  每个预制体的结构如下:

   

  

需要用到的UI组件

  在之前的UGUI简单介绍中列举了一些UI控件,这些控件上并不一定默认就有我们需要用到的组件,比如:

  1. CanvasGroup

  

  这个组件可以放在Canvas上,通过对于Alpha值的控制,实现面板渐隐渐显的效果。如果安装了DoTween插件,可以实现一个简单的显示动画效果(效果曲线可以参照:Easing Functions Cheat Sheet) 

       canvasGroup = gameObject.AddComponent<CanvasGroup>(); 
       canvasGroup.interactable = false;  //还没显示完全时不允许交互
       canvasGroup.DOFade(0f, 1f); //安装DoTween插件,控制Alfa值,1s内透明度变成0

       //1.5s内按照OutExpo动画曲线显现,完成后回调
       canvasGroup.DOFade(1f, 1.5f).SetEase(Ease.OutExpo).OnComplete(()=>
       {//完成显示之后的回调
          action?.Invoke();  //执行回调
          canvasGroup.interactable = true;  // 面板可以交互
       });  

  2. Button等控件的OnClick()监听

  Button按钮是交互性最强的按钮,其身上的OnClick(),作为按钮按下的监听,在场景中的使用非常频繁。绑定监听的方法可以按以下方式:

  方法一:直接在OnClick()面板添加脚本节点,并指定回调函数

   方法二:代码中动态设置:

        button = transform.GetComponent<Button>();
        button.onClick.AddListener(()=>
        {
            Debug.Log("没想好要干嘛");
        });

  3. EventTrigger

  Button中提供了按钮被按下的事件,而EventTrigger中提供了种类更加丰富的事件

    public enum EventTriggerType
    {
        PointerEnter, //鼠标进入
        PointerExit,  //鼠标离开
        PointerDown,  //鼠标按下
        PointerUp,    //鼠标抬起
        PointerClick, //鼠标点击(鼠标抬起时已不在原UI上时不会触发,在PointerUp之后调用)
        Drag,         //鼠标拖拽
        Drop,         //拖拽结束时鼠标不在被拖拽UI上并且在另外一个UI上时触发(在PointerUp之后)
        Scroll,       //滑轮滚动时
        UpdateSelected, //被选中后的每一帧
        Select,       //在被选中时
        Deselect,     //结束选中时
        Move,         //按方向键时
        InitializePotentialDrag,  //初始化拖拽(在PointerDown之后,PoinerUp之前调用,点击就会调用)
        BeginDrag,    //拖拽开始(鼠标按下不移动不会触发)
        EndDrag,      //拖拽结束
        Submit,       //默认为Enter键
        Cancel        //默认为Enter键
    }

  添加监听及回调的方式和OnClick()一样,也可以在面板中添加,或者在脚本中动态添加。

  方法一:点击"AddNewEventType"->找到需要绑定的事件,点击“+”号键,并添加回调函数

 

   方法二:代码中添加

        EventTrigger.Entry entry = new EventTrigger.Entry();
        entry.callback = new EventTrigger.TriggerEvent();
        entry.callback.AddListener(callBack);
        entry.eventID = EventTriggerType.PointerClick; //添加PointerClick类型的事件
        transform.GetComponent<EventTrigger>().triggers.Add(entry);

建立UI工具集

   建立一个基类UIBase.cs,管理所有的UI节点,并且设置一些工具控制面板的初始化、显示、隐藏、添加事件等,之后在场景中可以方便地调用。

  1. 管理UI节点

 首先,我们需要获取并管理所有的UI节点。不过从上面的UI结构图中可以看到,UI的层级结构和节点非常多,不能每次使用时都遍历一遍。因此,在管理这些数据之前,先要使用Tag标签把UI控件分类,需要经常交互的控件使用“UIEvent”标签,仅需控制显示的使用“UIGO”标签,其他一些完全不需要操控的UI节点就不使用标签。

  接着,可以使用以下两种方式管理所有节点:

  方法1:建立字典

    //存储一下需要用到的UIGO,以防止每次都去所有节点查找一遍
    private Dictionary<string, GameObject> uiItem;

  然后在面板初始化的时候,把所有的节点都加入到字典中去。(详见下面的初始化工具代码)

  方法2:直接拖进面板

    如果节点不多的话,可以建立一批public的GameObject,简单粗暴地将相应的UI节点直接拖进面板,例如:

        [Header("MENUS")]
        [Tooltip("The Menu for when the MAIN menu buttons")]
        public GameObject mainMenu;
        [Tooltip("THe first list of buttons")]
        public GameObject firstMenu;
        [Tooltip("The Menu for when the PLAY button is clicked")]
        public GameObject playMenu;
        [Tooltip("The Menu for when the EXIT button is clicked")]
        public GameObject exitMenu;
        [Tooltip("Optional 4th Menu")]
        public GameObject extrasMenu;

  然后一个一个对应拖进去

以下详细介绍一下UIBase.cs实现的过程:

  2.  UIBase包含了以下的工具

  (1)初始化——需要实现的工作有:遍历UI节点并将它们放入字典管理、给“UIGO”标签的节点挂上EventTrigger组件、给根节点(Canvas)挂上CanvasGroup组件。

    private Dictionary<string, GameObject> uiItem;  //字典用于存储UI节点

    public virtual void InitPanel(UnityAction action=null)
    {
        uiItem= new Dictionary<string, GameObject>();//实例化字典对象
        List<Transform> list= new List<Transform>(); //建立一个列表用于存储节点
        FindChild(transform,list);  
        //使用自定义的FindChild方法遍历当前节点以下的所有子节点,并存入list

        foreach (var item in list)
        {
           if(!uiItem.ContainsKey(item.name))
              uiItem.Add(item.name, item.gameObject);//把这个节点放进字典

           //判断如果是按钮组件,就添加EventTrigger
            if(item.CompareTag("UIEvent"))
            {
                var trigger=item.gameObject.AddComponent<EventTrigger>();
                if (trigger.triggers.Count== 0)
                   trigger.triggers=new List<EventTrigger.Entry>(); 
            }               
        }
        canvasGroup = gameObject.GetComponent<CanvasGroup>();
        //获取UI根节点的CanvasGroup,以便于控制实现面板慢慢显现的特效
        action?.Invoke();  //如果有回调的话回调
    }

  其中,遍历子节点的方法可以归纳称为一个小工具:

    //一个查找子物体的工具,从当前节点开始找
    private void FindChild(Transform father,List<Transform> list)
    {
        if(father.childCount> 0)
        {
            for(int i=0;i<father.childCount;i++)
            {
                list.Add(father.GetChild(i));
                FindChild(father.GetChild(i),list);
            }
        }
        return;
    }

  (2)显示面板——如果不使用DoTween,而是直接显示出来

    //显示面板
    public virtual void Show(UnityAction action=null)
    {
        gameObject.SetActive(true);  //节点激活
        action?.Invoke();
    }

    如果使用DoTween做一个渐显的小动画,那么Show工具写成下面:

    //显示面板
    public virtual void Show(UnityAction action=null)
    {
        gameObject.SetActive(true);  //节点激活
        switch(showType) //显示的方式ShowType定义为一个枚举数据
        {
            case ShowType.Normal:   
                action?.Invoke();
                break;
            case ShowType.Fade:
            {
                if (canvasGroup == null)
                    { canvasGroup = gameObject.AddComponent<CanvasGroup>(); }
                canvasGroup.interactable = false;  //还没显示完全时不允许交互
                canvasGroup.DOFade(0f, 0f); //DoTween插件,控制Alfa值,透明度变成0,1s时间
                canvasGroup.DOFade(1f, 1.5f).SetEase(Ease.OutExpo).OnComplete(()=>
                {
                    action?.Invoke();
                    canvasGroup.interactable = true;  // 可以交互
                });  //1.5s内按照OutExpo动画曲线显现,完成后回调
            }
                break;
        }
    }   

 其中显示方式ShowType,归纳成一个枚举数:

public enum ShowType
{
    Normal, Fade, Mask      //直接显示,渐显效果,遮罩
}

  (3)隐藏面板——结构与显示面板相似,为了节省篇幅,这里就不使用DoTween了,如果需要使用DoTween,可以把上面的显示面板代码复制修改一下

    //隐藏
    public virtual void Hide(UnityAction action=null)
    {
      action?.Invoke();
      gameObject.SetActive(false);
    }

  (4)获取组件——UI组件类型繁多,所以使用泛型方法来获取组件

    protected T GetComponent<T>(string name) where T : MonoBehaviour
    {
        if (!uiItem.ContainsKey(name)) return null;  //如果没有这个组件就返回空
        return uiItem[name].GetComponent<T>();
    }

  (5)给控件添加EventTrigger组件、注册事件——在上面已经说明过方法了

    public void AddEventTrigger(string controlName,EventTriggerType type,
        UnityAction<BaseEventData> callBack)
    {
        //从字典中获取控件,并添加EventTrigger组件
        if(!uiItem.ContainsKey(controlName)) return;
        if (uiItem[controlName].gameObject.GetComponent<EventTrigger>()==null)
            uiItem[controlName].AddComponent<EventTrigger>();
        //添加Entry、监听、回调
        EventTrigger.Entry entry = new EventTrigger.Entry();
        entry.callback = new EventTrigger.TriggerEvent();
        entry.callback.AddListener(callBack);  
        entry.eventID = type;
        uiItem[controlName].GetComponent<EventTrigger>().triggers.Add(entry);
    }

  以上这是总的UI面板管理工具,具体到每个UI面板,如主面板Canvas_Main、退出面板Canv_EXIT,有些游戏项目中还有背包面板、排行榜面板等等,是需要根据不同情况重写上面这些工具。下面就以主面板为例,写一下主面板管理的脚本MainUi.cs

建立分面板的管理工具——以主面板MainUi为例

  对于一个分面板来说,需要做的工作有:重写初始化工具、显示工具等;在关键节点上添加组件、事件和回调;获取重要节点的组件,比如图片、文字等组件,以备后续控制等等。

public class MainUI : UITools
{//针对MainUI节点的工具,之后会使用UIManager动态挂在主面板上,提前挂好也可以
    
    public override void Init(UnityAction action = null) //重写UITools的Init()
    {
        base.Init(action);   
        //给Button_Play按钮添加一个PointerClick事件和回调
        AddEventTrigger("Button_Play", EventTriggerType.PointerClick, OnEventStart);
        //给Button_Extras按钮添加一个PointerClick事件和回调
        AddEventTrigger("Button_Extras", EventTriggerType.PointerClick, OnEventEnd);
        //给Button_Exit按钮添加一个PointerClick事件和回调
        AddEventTrigger("Button_Exit", EventTriggerType.PointerClick, OnEventExit);
    }

    private void OnEventStart(BaseEventData data)
    {
        UIManager.Instance.ShowPanel<ExtraUi>("ExtraPanel", "EXTRAS", null, UIManager.PanelType.Extra);  //点Button_Play按钮显示EXTRAS面板
    }

    private void OnEventEnd(BaseEventData data)
    {
        UIManager.Instance.HidePanel("ExtraPanel"); //点Button_Extras按钮隐藏EXTRAS面板
    }

    private void OnEventExit(BaseEventData data)
    {
        UIManager.Instance.ShowPanel<ExitUi>("ExitPanel", "EXIT", null, UIManager.PanelType.UP);  //点Button_Exit按钮弹出询问是否退出面板
    }
}

  以上就是主面板MainUi需要用到的工具,其他面板的工具类也可以参照它来写。其中,在2个回调方法中,用到了UIManager,它将总体管理整个UI节点的初始化、布局等,可以参照下一篇的UIManager的定义。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

软件设计师第4题

首先&#xff0c;我是备考2023年上半年的考试。 一、历年考试题 历年的考题如下&#xff0c;从表中分析可以看出&#xff0c;动态规划法、排序算法、回溯法、分治法是很大概率考察的算法&#xff0c;尤其是动态规划法&#xff0c;本身其理解难度较高&#xff0c;且可以出的题型…

【计网】第二章 物理层

文章目录 物理层一、物理层的基本概念二、数据通信的基础知识2.1 数据通信系统的模型2.2 有关信道的基本概念2.3 信道的极限容量2.3.1 奈奎斯特定理2.3.1 香农定理2.3.2 信噪比 三、物理层下面的传输媒体3.1 导引型传输媒体3.2 非导引型传输媒体 四、信道复用技术4.1 频分复用 …

【小沐学Python】Python实现在线电子书(Sphinx + readthedocs + github + Markdown)

文章目录 1、简介2、安装3、创建测试工程4、项目文件结构5、编译为本地文件6、编译为http服务7、更改样式主题8、支持markdown9、修改文档显示结构10、项目托管到github11、部署到ReadtheDocs结语 1、简介 Sphinx 是一个 文档生成器 &#xff0c;您也可以把它看成一种工具&…

STC15WProteus仿真HX711电子秤串口计价称重4x4键盘STC15W4K32S4

STC15WProteus仿真HX711电子秤串口计价称重4x4键盘STC15W4K32S4 Proteus仿真小实验&#xff1a; STC15WProteus仿真HX711电子秤串口计价称重4x4键盘STC15W4K32S4 功能&#xff1a; 硬件组成&#xff1a;STC15W4K32S4单片机 LCD12864显示器4x4矩阵键盘HX711电子秤 1.单片机通…

操作教程:EasyCVR视频融合平台如何配置平台级联?

EasyCVR视频融合平台基于云边端一体化架构&#xff0c;可支持多协议、多类型设备接入&#xff0c;在视频能力上&#xff0c;平台可实现视频直播、录像、回放、检索、云存储、告警上报、语音对讲、电子地图、集群、智能分析以及平台级联等。平台可拓展性强、开放度高、部署轻快&…

NUCLEO-F411RE RT-Thread 体验 (3) - GCC环境 uart驱动的移植以及console的使用

NUCLEO-F411RE RT-Thread 体验 (3) - GCC环境 uart驱动的移植以及console的使用 1、准备工作 在第一节里&#xff0c;我们用stm32cubemx将pa2 pa3管脚配置成usart2&#xff0c;用于跟st-link虚拟串口的打印用&#xff0c;那么我们先重定向printf函数&#xff0c;看这条通道是…

2009年iMac装64位windows7

前言&#xff1a;单位领导会花屏的iMac&#xff08;24寸 2009年初版&#xff09;我捡来用&#xff0c;应该大约是在2020年安装了32位windows7&#xff0c;发现不安装显卡驱动便不会花屏死机&#xff0c;于是就当简单的上网机用着&#xff0c;毕竟iMac的显示屏还是蛮不错的。现在…

windows系统安装显卡驱动软件和CUDA11.1的详细教程

深度学习目标检测框架在进行图像计算时需要GPU进行加速&#xff0c;需要用到硬件GPU显卡&#xff0c;目标检测框架和硬件GPU建立联系需要通过①显卡驱动软件&#xff1b;②CUDA软件依次建立联系。这两个软件&#xff0c;可直接从NVIDIA官网下载&#xff0c;版本没有非常严格的需…

python获取某乎热搜数据并保存成Excel

python获取知乎热搜数据 一、获取目标、准备工作二、开始编码三、总结 一、获取目标、准备工作 1、获取目标&#xff1a; 本次获取教程目标&#xff1a;某乎热搜 2、准备工作 环境python3.xrequestspandas requests跟pandas为本次教程所需的库&#xff0c;requests用于模拟h…

WinDbg安装入坑3(C#)

由于作者水平有限&#xff0c;如有写得不对的地方&#xff0c;请指正。 使用WinDbg的过程中&#xff0c;坑特别的多&#xff0c;对版本要求比较严格&#xff0c;如&#xff1a; 1 32位应用程序导出的Dump文件要用32位的WinDbg打开&#xff0c;想要没有那么多的问题&#xf…

SpringCloud Eureka注册服务提供者(七)

这里我们在原来的服务提供者项目 microservice-student-provider-1001 上面直接修改&#xff1a; 首先pom.xml修改&#xff0c;加上eureka客户端依赖&#xff1a; <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>…

【正点原子STM32连载】 第三十二章 光敏传感器实验 摘自【正点原子】STM32F103 战舰开发指南V1.2

第三十二章 光敏传感器实验 本章&#xff0c;我们将学习使用STM32开发板板载的一个光敏传感器。我们还是要使用到ADC采集&#xff0c;通过ADC采集电压&#xff0c;获取光敏传感器的电阻变化&#xff0c;从而得出环境光线的变化&#xff0c;并在TFTLCD上面显示出来。 本章分为如…

VSCode 安装配置教程详解包含c++环境配置方法

vscode安装教程及c环境配置详解 vscode下载安装下载C扩展插件VScode C环境配置配置环境变量检查 MinGW 安装配置编译器&#xff1a;配置构建任务检查是否安装了编译器配置完毕 vscode下载安装 地址&#xff1a;官网下载地址 直接打开下载好的.exe文件进行安装即可&#xff0…

“暗网议会”如今已成为现实

图片来源:Marcin Balcerzak 最近&#xff0c;“暗网议会”已经成为了网络犯罪分子试图证明自己影响力的最新流行语&#xff0c;安全内部人士对这个词也很感兴趣。 上周五&#xff0c;臭名昭著的亲俄黑客组织Killnet在其电报威胁帖子中使用了这个词语。随后&#xff0c;twitte…

SPEC 2006 gcc version 8.3.0 (Uos 8.3.0.3-3+rebuild) x86_64 源码编译tools 错误处理笔记

编译tools 拷贝tools到安装目录 cp /mnt/iso/tools /opt/speccpu2006/ -r 执行编译 su rootcd /opt/speccpu2006/tools/src sh -x buildtools 错误 undefined reference to __alloca 编辑./make-3.82/glob/glob.c&#xff0c;注释掉以下宏判断 you should not run config…

5-垃圾回收

目录 1.死亡对象的判断算法 1.1.引用计数算法 1.2.可达性分析算法&#xff08;主流&#xff09; PS&#xff1a;强引用、软引用、弱引用、虚引用 2.垃圾回收算法 2.1.标记-清除算法 2.2.复制算法 2.3.标记-整理算法 2.4.分代算法&#xff08;主流&#xff09; PS&…

二进制方式部署kubernetes集群

二进制方式部署kubernetes集群 1、部署k8s常见的几种方式 1.1 kubeadm Kubeadm 是一个 k8s 部署工具&#xff0c;提供 kubeadm init 和 kubeadm join&#xff0c;用于快速部署 Kubernetes 集群。 Kubeadm 降低部署门槛&#xff0c;但屏蔽了很多细节&#xff0c;遇到问题很难…

TDesign电商小程序模板解析02-首页功能

目录 1 home.json2 goods-list组件3 goods-card组件总结 上一篇我们搭建了底部的导航条&#xff0c;这一篇来拆解一下首页的功能。首页有如下功能 可以进行搜索显示轮播图横向可拖动的页签图文卡片列表 1 home.json 因为是要使用组件库的组件搭建页面&#xff0c;自然是先需要…

【win11+Visual Studio 2019 配置 PCL 1.12.1 的经验总结分享】

点云pc库的下载与安装参考另外一篇文章&#xff0c;链接&#xff1a; https://blog.csdn.net/weixin_47869094/article/details/131270772?spm1001.2014.3001.5501 各种教程里面这都很好&#xff0c;就不赘述了&#xff0c;当然&#xff0c;这里也给出一个个人认为不错的安装…

java项目之病人跟踪治疗信息管理系统(ssm+vue)

风定落花生&#xff0c;歌声逐流水&#xff0c;大家好我是风歌&#xff0c;混迹在java圈的辛苦码农。今天要和大家聊的是一款基于ssm的病人跟踪治疗信息管理系统。项目源码以及部署相关请联系风歌&#xff0c;文末附上联系信息 。 &#x1f495;&#x1f495;作者&#xff1a;风…