UnityVR--UIManager--UI管理1

news/2025/3/15 5:00:38/

目录

前言

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按钮,显示其中一个Loading面板,这个面板就要放在主面板节点的下面,显示时覆盖在主面板上。

  *注:在不少项目中,大部分的UI面板都是作为预制体的形式存在于Resource资源文件夹中,而场景中只留下UI根节点(空)、UICamera、Main/Middle/……等存放各部分面板的节点(均为空),以及EventSystem。

需要用到的组件

  在之前的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方法遍历当前节点以下的所有子节点,并存入listforeach (var item in list){if(item.CompareTag("UIEvent"))  //判断列表中找到的是否有UIEvent的标签{//有的话就添加EventTrigger组件var trigger=item.gameObject.AddComponent<EventTrigger>();if (trigger.triggers.Count == 0){//新建的EventTrigger列表为空,添加一个新Entry列表trigger.triggers=new List<EventTrigger.Entry>(); }uiItem.Add(item.name, item.gameObject); //并且把这个节点添加到字典中}if (item.CompareTag("UIGO")){//如果UI节点的标签是UIGO,也放入到字典中uiItem.Add(item. name, item.gameObject);}}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节点的工具private TMP_Text IntroText;  // 获取一个Text控件以便于输出文字private GameObject Panel_EXTRAS;  //获取一个隐藏的面板public override void Init(UnityAction action = null) //重写UITools的Init(){base.Init(action);   //给Button_Play按钮添加一个PointerClick事件和回调AddEventTrigger("Button_Play", EventTriggerType.PointerClick, OnEventStart);Panel_EXTRAS = GetGameObject("EXTRAS"); //获取EXTRAS节点IntroText = GetComponent<TMP_Text>("IntroText");  //获取文字节点}public override void Show(UnityAction action = null){//重写Show工具base.Show(action); IntroText.text = "这是Main面板"; }private void OnEventStart(BaseEventData data){Hide(() =>    //按下Button_Play按钮,隐藏主面板,显示EXTRAS面板{UIManager.Instance.ShowPanel<EXTRASUI>("EXTRASUI", "EXTRASUI"); });}
}

  以上就是主面板MainUi需要用到的工具,使用到了UIManager的显示面板ShowPanel,可以参照下一篇的UIManager的定义。

  其他的面板管理都可以参照此例,比如上面需要显示的EXTRAS面板,还需要有内容图片的排序工具,就可以在EXTRASUI.cs中定义。


http://www.ppmy.cn/news/405048.html

相关文章

imac html5播放器,超给力的五款Mac最佳高清音乐播放器

大多数Mac用户喜欢使用iTunes或一些流媒体服务来管理和收听他们的音乐。当然&#xff0c;如果您是喜欢高分辨率音频的发烧友&#xff0c;那么有iTunes就够了。如果您是高保真格式音乐发烧友&#xff0c;则iTunes可能不能满足您的要求。不过没关系&#xff0c;你可以选择下载一些…

一个女测试工程师的大厂日常

今天给大家分享两个朋友的故事&#xff0c;他们分别在国内两家顶尖的互联网大厂&#xff0c;一个在头条&#xff0c;一个在蚂蚁。 头条的故事 头条的主人公&#xff0c;在入职后的一年里&#xff0c;晚上十点半下班是比较早了&#xff0c;基本上都是十一点半左右下班&#xff…

C语言的几种缺陷及其规避方法

一、C语言的几种缺陷 C语言作为一种老牌编程语言&#xff0c;在其诞生时代的背景下是十分先进的&#xff0c;为编程领域的发展做出了重要贡献。但是&#xff0c;随着计算机体系结构、软硬件环境的不断演进&#xff0c;C语言所存在的一些缺点也逐渐凸显出来。以下是C语言的一些缺…

黑客是怎样练成的?

网学黑客技术的人越来越多了&#xff0c;不少人都不知道该怎么学&#xff0c;今天就来详细的说一说黑客是如何炼成的。 首先&#xff0c;什么是黑客&#xff1f; 黑客 &#xff1a;泛指擅长IT技术的电脑高手 黑客一词&#xff0c;源自英文Hacker&#xff0c;早期其实就是一群…

如何在 macOS 中检查键盘、鼠标和触控板的电池电量

无线连接的外围设备是现代办公室的福音&#xff0c;特别是当我们在家工作时&#xff0c; 不处理电缆有助于保持理智和组织。电池供电的鼠标、触控板和键盘在通过 USB 或可充电电池充满一次电后可以工作数周到数月。 但是 Apple 不会在明显的地方显示此电量&#xff0c;因为它会…

vue搭建项目(二)token相关

在vue中&#xff0c;token的意思是“令牌”&#xff0c;是服务端生成的字符串&#xff0c;是客户端进行请求的一个标识&#xff1b;当用户第一次登录后&#xff0c;服务端生成一个token并返回给客户端&#xff0c;以后客户端只需要带着token请求数据即可&#xff0c;不需再使用…

2020-09-15 JAVA面试题整理

文章目录 一、Java基础系列面试题二 Java 面试题&#xff08;二&#xff09;四、Redis面试题四、Redis面试题七、Spring Boot 面试题九、微服务 面试题十一、RabbitMQ 面试题十二、Dubbo 面试题十三、Elasticsearch 面试题十四、Linux 面试题 2020年字节跳动Java面试题附答案解…

一台电子计算机每秒,一台电子计算机每秒可运行4×10

多 功 能 的 生 物 标 用计算机代替人类的思维与行为一直是计算机研究人员梦寐以求的理想。 就电视的后代来说&#xff0c;未来的主要业务是存储和转发数百万台远距离计算机的数字数据。这些机器将能调出或发送世界上任何地方的影片或文件、新闻和剪报、课程和目录。这与目前以…