UnityVR--UIManager--UI管理1

2023-11-21 01:10
文章标签 ui 管理 unityvr uimanager

本文主要是介绍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插件,可以实现一个简单的显示动画效果(缓动效果曲线可以参照:https://easings.net/) 

       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方法遍历当前节点以下的所有子节点,并存入listforeach (var item in list){if(!uiItem.ContainsKey(item.name))uiItem.Add(item.name, item.gameObject);//把这个节点放进字典//判断如果是按钮组件,就添加EventTriggerif(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的定义。

这篇关于UnityVR--UIManager--UI管理1的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/398742

相关文章

HarmonyOS学习(七)——UI(五)常用布局总结

自适应布局 1.1、线性布局(LinearLayout) 通过线性容器Row和Column实现线性布局。Column容器内的子组件按照垂直方向排列,Row组件中的子组件按照水平方向排列。 属性说明space通过space参数设置主轴上子组件的间距,达到各子组件在排列上的等间距效果alignItems设置子组件在交叉轴上的对齐方式,且在各类尺寸屏幕上表现一致,其中交叉轴为垂直时,取值为Vert

综合安防管理平台LntonAIServer视频监控汇聚抖动检测算法优势

LntonAIServer视频质量诊断功能中的抖动检测是一个专门针对视频稳定性进行分析的功能。抖动通常是指视频帧之间的不必要运动,这种运动可能是由于摄像机的移动、传输中的错误或编解码问题导致的。抖动检测对于确保视频内容的平滑性和观看体验至关重要。 优势 1. 提高图像质量 - 清晰度提升:减少抖动,提高图像的清晰度和细节表现力,使得监控画面更加真实可信。 - 细节增强:在低光条件下,抖

软考系统规划与管理师考试证书含金量高吗?

2024年软考系统规划与管理师考试报名时间节点: 报名时间:2024年上半年软考将于3月中旬陆续开始报名 考试时间:上半年5月25日到28日,下半年11月9日到12日 分数线:所有科目成绩均须达到45分以上(包括45分)方可通过考试 成绩查询:可在“中国计算机技术职业资格网”上查询软考成绩 出成绩时间:预计在11月左右 证书领取时间:一般在考试成绩公布后3~4个月,各地领取时间有所不同

安全管理体系化的智慧油站开源了。

AI视频监控平台简介 AI视频监控平台是一款功能强大且简单易用的实时算法视频监控系统。它的愿景是最底层打通各大芯片厂商相互间的壁垒,省去繁琐重复的适配流程,实现芯片、算法、应用的全流程组合,从而大大减少企业级应用约95%的开发成本。用户只需在界面上进行简单的操作,就可以实现全视频的接入及布控。摄像头管理模块用于多种终端设备、智能设备的接入及管理。平台支持包括摄像头等终端感知设备接入,为整个平台提

从状态管理到性能优化:全面解析 Android Compose

文章目录 引言一、Android Compose基本概念1.1 什么是Android Compose?1.2 Compose的优势1.3 如何在项目中使用Compose 二、Compose中的状态管理2.1 状态管理的重要性2.2 Compose中的状态和数据流2.3 使用State和MutableState处理状态2.4 通过ViewModel进行状态管理 三、Compose中的列表和滚动

Sentinel 高可用流量管理框架

Sentinel 是面向分布式服务架构的高可用流量防护组件,主要以流量为切入点,从限流、流量整形、熔断降级、系统负载保护、热点防护等多个维度来帮助开发者保障微服务的稳定性。 Sentinel 具有以下特性: 丰富的应用场景:Sentinel 承接了阿里巴巴近 10 年的双十一大促流量的核心场景,例如秒杀(即突发流量控制在系统容量可以承受的范围)、消息削峰填谷、集群流量控制、实时熔断下游不可用应

NGINX轻松管理10万长连接 --- 基于2GB内存的CentOS 6.5 x86-64

转自:http://blog.chinaunix.net/xmlrpc.php?r=blog/article&uid=190176&id=4234854 一 前言 当管理大量连接时,特别是只有少量活跃连接,NGINX有比较好的CPU和RAM利用率,如今是多终端保持在线的时代,更能让NGINX发挥这个优点。本文做一个简单测试,NGINX在一个普通PC虚拟机上维护100k的HTTP

PMBOK® 第六版 规划进度管理

目录 读后感—PMBOK第六版 目录 规划进度管理主要关注为整个项目期间的进度管理提供指南和方向。以下是两个案例,展示了进度管理中的复杂性和潜在的冲突: 案例一:近期,一个长期合作的客户因政策要求,急需我们为多家医院升级一个小功能。在这个过程中出现了三个主要问题: 在双方确认接口协议后,客户私自修改接口并未通知我们,直到催进度时才发现这个问题关于UI设计的部分,后台开发人员未将其传递给

PHP原理之内存管理中难懂的几个点

PHP的内存管理, 分为俩大部分, 第一部分是PHP自身的内存管理, 这部分主要的内容就是引用计数, 写时复制, 等等面向应用的层面的管理. 而第二部分就是今天我要介绍的, zend_alloc中描写的关于PHP自身的内存管理, 包括它是如何管理可用内存, 如何分配内存等. 另外, 为什么要写这个呢, 因为之前并没有任何资料来介绍PHP内存管理中使用的策略, 数据结构, 或者算法. 而在我们

C++学习笔记----6、内存管理(四)---- 通常的内存陷阱(2)

3、Windows环境下使用Visual C++发现并修复内存渗露         内存渗露很难跟踪是因为你无法很容易地看着内存并且看到什么对象处于使用中,一开始在哪儿分配的内存。然而,是有程序可以为你做到这一点的。内存渗露检测工具有昂贵的专业软件包,也有免费下载的工具。如果你是在Microsoft Visual C++环境下工作,它的排错工具库有内建的对于内存渗露检测的支持。该内存检测默认没有