【Unity-UGUI】UGUI知识汇总

目录

  • 前言
  • [1 UGUI系统原理](#1 UGUI系统原理)
  • [2 事件系统](#2 事件系统)
    • [2.1 EventSystem](#2.1 EventSystem)
    • [2.2 InputModules](#2.2 InputModules)
    • [2.3 Raycasters](#2.3 Raycasters)
    • [2.4 协作](#2.4 协作)
  • [3 UGUI系统的组件](#3 UGUI系统的组件)
    • [3.1 Image和RawImage](#3.1 Image和RawImage)
    • [3.2 Mask和RectMask2D](#3.2 Mask和RectMask2D)
  • 扩展

前言

记录一些最近学到的有关UGUI的知识。

参考

知乎:6千字带你入门UGUI源码

书籍:《Unity3D高级编程》

1 UGUI系统原理

UGUI是3D网格下建立起来的UI系统,它的每个可显示的元素都是通过3D模型网格的形式建立起来的。当UI系统被实例化时,UGUI系统首先要做的就是构建网格。

也就是说,Unity在制作一个UI元素时,都会先构建一个方形网格,再将图片放入网格内。可以理解成构建了一个3D模型,用一个网格绑定一个材质球,材质球内存放要显示的图片。

但这里有个问题,就是如果每个元素都生成一个模型且绑定一个材质球存入一张图片,那么界面上成千上万的元素就会有成千上万的材质球和图片,显然是不可能的,因为如果这样的话,GPU需要对每个材质球和网格都进行渲染,GPU的负担会很重。

UGUI确实对这一部分进行了优化,它将一部分相同类型的图片合并成一张图,然后将拥有相同图片、相同着色器的材质球指向同一个材质球,并且把分散的模型网格合并起来。这样就生成几个大网格、几个不同图集的材质球和几张图集(合并这一步是由Canvas实现的)。

不过UGUI并不是把所有的网格和材质球合并成一个,它只是把相同层级的元素,以及相同层级上拥有相同材质球参数的进行合并。合并成一个网格,就相当于一个静止的模型,如果有任何元素被移动或者销毁,或者元素的参数被改变,就需要摧毁原来的网格,重新进行构建。这样的操作会消耗很多的CPU内存,因此我们要想方设法地合并更多元素,减少重构次数。这也是UGUI性能优化的一个方向之一。

UI重建(rebuild)

2 事件系统

UGUI的事件系统由以下三个子版块组成:

2.1 EventSystem

事件系统主要是基于输入(键盘、鼠标、触摸或自定义输入)向应用程序中的对象发送事件,当然这需要其他组件的配合。当你在GameObject中添加EventSystem时,你会发现它并没有太多的功能,这是因为EventSystem本身被设计成事件系统不同模块之间通信的管理者和推动者,它主要包含以下功能:

  • 管理正在使用的输入模块
  • 管理哪个游戏对象被选中
  • 管理射线检测

管理输入模块(InputModule)

EventSystem负责管理所有的输入模块(InputModule),它在Update中调用TickModules更新每一个模块,并在满足条件时调用模块的Process方法。

管理选中的游戏对象

当场景中有了新的被选中的对象,会通知之前选中的对象执行OnDeselect事件,通知新的对象执行OnSelect事件。

管理射线检测

EventSystem中,还有一个非常重要的函数RaycastAll(),主要是获取目标。这个方法会首先获取所有的BaseRaycast对象,调用其Raycast方法,然后对最后得到的结果进行排序(大部分情况下按深度进行排序,也有一些情况下会使用距离、排序顺序(SortingOrder,如果是UI则根据Canvas面板的Sort order,3D物体默认是0或者根据Sorting Layer作为排序依据))。

PS:在看UGUI性能优化时,有一条是将无交互事件的UI的Raycast Target字段设为false,我怀疑可能就是为了减少这里的BaseRaycast对象。

2.2 InputModules

输入模块是配置和定制事件系统主逻辑的地方。 自带的输入模块有两个,一个是为独立输入(StandaloneInputModule),另一个是为触摸输入(TouchInputModule)。 StandaloneInputModule是PC、Mac&Linux上的具体实现,而TouchInputModule是IOS、Android等移动平台上的具体实现,每个模块都按照给定配置接收和分派事件。 运行EventSystem后,它会查看附加了哪些输入模块,并将事件传递给特定的模块。

而事件执行则通过ExecuteEvent类,这个类中定义了许多接口,比如鼠标按下、点击、拖拽等。

2.3 Raycasters

Raycasters负责确定目标对象。给定一个屏幕空间位置,它们将收集所有潜在目标,找出它们是否在给定位置下,然后返回离屏幕最近的对象。 系统提供了以下几种类型的Raycaster:

  • Graphic Raycaster: 检测UI元素
  • Physics Raycaster: 用于3D物理元素
  • Physics 2D Raycaster: 用于2D物理元素

2.4 协作

EventSystem会在Update中调用输入模块的Process方法来处理输入消息。PointerInputModule的Process方法会调用EventSystem中的RaycastAll方法进行射线检测。RaycastAll又会调用所有BastRaycaster的Raycast方法执行具体的射线检测操作,用以获取屏幕某个点下的所有目标。

获取完点击目标后,又会回到PointerInputModule,对其触发那些事件接口(IPointerClickHandler之类的)并传入PointerEventData参数 => 使用冒泡排序通知,直到有能处理对应IEventSystemHandler的UI接收为止(比如Button上的Text无点击事件,那就父物体Button接收)。

举例:

当你点击了一个Button组件,首先你的行为会在EventSystem的Update中被输入模块的Process方法被抓取到,之后输入模块就会调用RaycastAll方法来得到所有屏幕下点击到的目标,最后通过冒泡的方式来找到第一个可以接收点击事件的UI目标。确定好UI目标后,对其执行点击事件。

3 UGUI系统的组件

3.1 Image和RawImage

Unity中的RawImage

RawImage从功能上可以看成是丐版的Image。

区别:

1.Image只能展示Sprite类型图片,RawImage则可以展示各种类型的图片(描述为Texture)。

2.Sprite 只能用在 Image 组件上,做2D and UI,Sprite可以理解为2D特意做的对Texture的封装。

2.Sprite可以做九宫格。

3.Sprite一般用在小图,可以打Atlas(图集)。

4.Texture基于纹理寻址模式,不能打包Atlas。

  1. UI 需要修改UV rect和用到寻址模式的,用Texture,否则用Sprite。

  2. 当图片尺寸很大导致合并图集效率太低,也可以用RawImage。

优势:

1.Image有Image的优势,Image可以九宫格拉伸。

2.RawImage有RawImage的优势,RawImage可以UV rect贴图的纹理寻址。

3.一般用Image,除了地图寻址,滚动之类的,从贴图哪个位置开始显示。

3.2 Mask和RectMask2D

它们是遮挡组件,可以将子节点下矩形区域外的内容剔除,这两个组件的区别主要是剔除方法不同。Mask使用顶点重构的方式剔除矩形区域外的部分,而RectMask2D组件则采用着色器的剔除方式。

扩展

UI穿透问题

问题描述:在Unity中,当UI元素和3D物体同时存在时,点击UI可能导致3D物体的点击事件也被触发。

查了一下资料似乎是使用OnMouseDown这个方法导致的,网上提到的解决方案是在摄像机上挂载Graphic Raycaster组件,然后使用OnPointerClick()方法替代OnMouseDown进行检测。

也有其他解决方案,不过也是围绕UI专用的射线检测Graphic Raycaster进行的:文章

相关推荐
牙膏上的小苏打233315 小时前
Unity Surround开关后导致获取主显示器分辨率错误
unity·主屏幕
Unity大海17 小时前
诠视科技Unity SDK开发环境配置、项目设置、apk打包。
科技·unity·游戏引擎
浅陌sss1 天前
Unity中 粒子系统使用整理(一)
unity·游戏引擎
维度攻城狮1 天前
实现在Unity3D中仿真汽车,而且还能使用ros2控制
python·unity·docker·汽车·ros2·rviz2
为你写首诗ge1 天前
【Unity网络编程知识】FTP学习
网络·unity
神码编程1 天前
【Unity】 HTFramework框架(六十四)SaveDataRuntime运行时保存组件参数、预制体
unity·编辑器·游戏引擎
菲fay1 天前
Unity 单例模式写法
unity·单例模式
火一线1 天前
【Framework-Client系列】UIGenerate介绍
游戏·unity
ZKY_241 天前
【工具】Json在线解析工具
unity·json
ZKY_242 天前
【Unity】处理文字显示不全的问题
unity·游戏引擎