大家好,我是佛系工程师☆恬静的小魔龙☆,不定时更新Unity开发技巧,觉得有用记得一键三连哦。
很早就想分享这个系列的文章,但是总是没有机会,最近就将这个系列整理一下,大家一起学习交流。
一、前言
首先,介绍一个UGUI,NGUI是UGUI的前身,Unity开发团队将NGUI的开发团队收到自己开发团队下,并且由此开发了UGUI。
UGUI系统是从Unity 4.6版本后才开始集成到Unity编辑器中。
UGUI的特点:
- 灵活
 - 快速
 - 可视化
 
对于开发者来说有很多的优点,比如说:
- 效率高
 - 实现效果好
 - 易于使用和拓展
 - 与Unity编辑器的兼容性高
 
这是本系列文章的第一篇:
【Unity3D-UGUI系列】(一)Canvas 画布组件详解
【Unity3D-UGUI系列】(二)Text文本组件详解
【Unity3D-UGUI系列】(三)Button 按钮组件详解
【Unity3D-UGUI系列】(四)Image 图片组件详解
【Unity3D-UGUI系列】(五)RawImage 显示纹理组件详解
【Unity3D-UGUI系列】(六)Panel 容器组件详解
【Unity3D-UGUI系列】(七)Dropdown 下拉菜单组件详解
【Unity3D-UGUI系列】(八)InputField 输入框组件详解
【Unity3D-UGUI系列】(九)Scrollbar 滚动条组件详解
【Unity3D-UGUI系列】(十)Slider 滑动条组件详解
【Unity3D-UGUI系列】(十一)Toggle 开关组件详解
【Unity3D-UGUI系列】(十二)ScrollView 滚动视图组件详解
二、Canvas 画布介绍
Canvas 画布,所有的UI元素的父物体,其他UI对象想要被渲染就在这个对象的子物体。
当创建一个UI元素的时候,如果没有Canvas 画布,就会自动创建一个画布。
在Unity的Hierarchy面板,选择"Create→UI→Canvas":

三、Canvas画布属性
选中创建的Canvas对象,在Inspect面板上详细了解一下Canvas画布的属性。
Canvas组件自带有三个组件,分别是Canvas、Canvas Scaler、Graphic Raycaster组件,下面就进行分别介绍:

3-1、Canvas:控制UI的渲染模式
Screen Space-Overlay —— 屏幕空间覆盖模式

属性  | 功能  | 
Pixel Perfect  | 使UI元素像素对应,效果就是边缘清晰不模糊  | 
Sort Order  | 多个Canvas时,数值越大越后渲染。值大的 画布,会挡住值小的  | 
Target Display  | 目标显示器,如果有多个屏幕的话可以选择  | 
Addtional Shader Channels  | 附加着色通道,决定Shader可以读取哪些相关数据,比如 法线、 切线 等数据。  | 
这个屏幕空间覆盖模式渲染模式,就是表示不管有没有相机去渲染场景,Canvas下的所有UI永远位于屏幕的前面,覆盖掉渲染场景显示的元素。
Screen Space-Camera —— 相机模式

属性  | 功能  | 
Pixel Perfect  | 使UI元素像素对应,效果就是边缘清晰不模糊  | 
Render Camera  | 渲染的相机  | 
Plane Distance  | Canvas与相机之间的距离  | 
Sorting Layer  | 画布的深度,指定了相机的渲染顺序  | 
Order In Layer  | 值越大,该UI越显示在前面  | 
这种渲染模式 适用于场景模型太多太大,在调整UI的时候挡住UI,让UI和渲染的相机移动到比较远的位置,就可以避免遮挡。并且Canvas 和 摄像机之间有一定的距离 , 可以在摄像机和 Canvas之间放置一些模型或粒子特效。
World Space —— 世界模式

属性  | 功能  | 
Event Camera  | 响应事件的相机  | 
Sorting Layer  | 画布的深度,指定了相机的渲染顺序  | 
Order in Layer  | 值越大,该UI越显示在前面  | 
Addtional Shader Channels  | 附加着色通道,决定Shader可以读取哪些相关数据,比如 法线、 切线 等数据。  | 
这种模式下 Canvas 就和场景中哄的其他游戏对象属性一样了,可以控制它的大小、旋转、缩放等。并且UI元素会根据在3D场景歌中的放置位置,来决定渲染在场景其他物体的前面还是后面。
这个模式,在我们需要将UI成为我们世界场景的一部分的时候非常有效。
3-2、Canvas Scaler:控制UI画布的放大缩放的比例
Constant Pixer Size —— 恒定像素

属性  | 功能  | 
Scale Factor  | 缩放因子  | 
Reference Pixels Per Uit  | 单位面积像素数量  | 
这种模式下 UI以像素为大小,同样的像素在不同的分辨率下尺寸不一样
Scale With Screen Size —— 屏幕尺寸比例

属性  | 功能  | 
Referencee Resolution  | 预设屏幕大小  | 
Screen Match Mode  | 缩放模式  | 
Match  | 宽高比  | 
这种缩放模式下的UI位置是根据屏幕的分辨率和设置的宽高比来调整UI的位置的,通常做屏幕UI自适应的时候都需要调整到这个缩放模式下。
Constant Physical Size —— 恒定尺寸

属性  | 功能  | 
Physical Unit  | 使用单位  | 
Fallback Screen DPI  | 备用屏幕的DPI  | 
Default Sprite DPI  | 默认图片的DPI  | 
Reference Pixels Per Uit  | 单位面积像素数量  | 
这种模式下 UI以像素为大小,在不同的分辨率下尺寸不一样
3-3、Graphic Raycaster:控制是否让UI响应射线点击

属性  | 功能  | 
Ignore Reversed Graphic  | 忽略反转的UI,UI反转后点击无效。  | 
Blocking Objects  | 阻挡点击物体,当UI前有物体时,点击前面的物体射线会被阻挡。  | 
Blocking Mask  | 阻挡层级,当UI前有设置的层级时,点击前面的物体射线会被阻挡。  | 
四、EventSystem系统详解
Canvas一同创建的还有一个EventSystem,这是一个基于Input的事件系统,可以对键盘、触摸、鼠标、自定义输入进行处理。
4-1、属性面板

Event System(Script)
属性  | 介绍  | 
First Selected  | 首选对象  | 
Send Navigation Events  | 发送导航事件  | 
Drag Threshold  | 拖动阈值  | 
Event System负责处理输入、射线投射以及发送事件。
一个场景中只能有一个Event System组件。
Standalone Input Module(Script)
属性  | 介绍  | 
Horizontal Axis  | 横轴  | 
Vertical Axis  | 纵轴  | 
Submit Button  | 提交按钮  | 
Canvel Button  | 取消按钮  | 
Input Actions Per Second  | 每秒输入动作  | 
Repeat Delay  | 重复延迟  | 
Force Module Active  | 力模块激活  | 
Standalone Input Module处理输入的鼠标或触摸事件,进行事件的分发。
4-2、运行流程分析
使用UGUI制作界面时,EventSystem的作用就像是为UGUI设计好的消息中心,它管理着所有能参与消息处理的UGUI组件,比如Panel、Image、Button等。
EventSytem组件,是消息机制的核心。
StandaloneInputModule,是负责产生输入的组件。
StandaloneInputModule继承自BaseInputModule实现类,类似的实现类Unity中还有另外几个,用户也可以自定义一个实现类用于事件处理。
但是,还少一个部分,那就是怎么确定某个事件是发给谁的,EventSystem响应的是用户的点击、触摸、拖动、长按之类的操作,那么EventSystem是怎么确定这些操作是针对谁的呢,所以还需要一个射线检测模块,来判断鼠标对准的UI是哪一个,这也就是GraphicPaycaster组件。
GraphicPaycaster专门负责Canvas下的UI的射线检测和计算问题。
至此,EventSystem在UGUI中的情况就比较清晰了,一个EventSystem对象负责管理所有事件相关对象,该对象下挂载了EventSystem组件和StandaloneInputModule组件,前者为管理脚本,后者为输入模块。Canvas对象下挂载了GraphicRaycaster负责处理射线相关运算,用户的操作都会通过射线检测来映射到UGUI组件上,InputModule将用户的操作转化为射线检测,Raycaster则找到目标对象并通知EventSystem,最后EventSystem发送事件让目标对象进行响应。
整理的流程如下图所示:

4-3、响应接口
UGUI的事件响应处理有多种方式,最简单而直接的一种应该就是通过实现特定接口的方法来处理事件响应了。
由于Canvas挂载了GraphicRaycaster组件,因此在Canvas对象之下的所有GUI对象都可以通过挂载脚本并且实现一些和事件相关的接口来处理事件,比如常见的IPointerClickHandler接口就是用于处理点击事件的接口。
可以实现的接口列表大概如下所示:
接口  | 说明  | 
IPointerEnterHandler - OnPointerEnter  | 当指针进入对象时调用  | 
IPointerExitHandler - OnPointerExit  | 当指针退出对象时调用  | 
IPointerDownHandler - OnPointerDown  | 当指针压在对象上时调用  | 
IPointerUpHandler - OnPointerUp  | 当指针被释放时调用(在原始按下的对象上调用)  | 
IPointerClickHandler - OnPointerClick  | 当在同一对象上按下和释放指针时调用  | 
IInitializePotentialDragHandler - OnInitializePotentialDrag  | 在找到拖动目标时调用,可用于初始化值  | 
IBeginDragHandler - OnBeginDrag  | 当拖动即将开始时,在拖动对象上调用  | 
IDragHandler - OnDrag  | 当发生拖动时在拖动对象上调用  | 
IEndDragHandler - OnEndDrag  | 当拖动完成时在拖动对象上调用  | 
IDropHandler - OnDrop  | 在拖动完成时对对象调用  | 
IScrollHandler - OnScroll  | 当鼠标滚轮滚动时调用  | 
IUpdateSelectedHandler - OnUpdateSelected  | 在选定的对象上调用  | 
ISelectHandler - OnSelect  | 当对象变成选定对象时调用  | 
IDeselectHandler - OnDeselect  | 被选中的对象被取消选中  | 
IMoveHandler - OnMove  | 当移动事件发生时调用(左、右、上、下等)  | 
ISubmitHandler - OnSubmit  | 在按下提交按钮时调用  | 
ICancelHandler - OnCancel  | 按下取消按钮时调用  | 
只要在挂载的脚本中实现所需要的接口,对应的事件回调也就可以执行了,下面例子演示了如何使用:
public class EventTest : MonoBehaviour, IPointerClickHandler, IDragHandler, IPointerDownHandler, IPointerUpHandler {
    public void OnDrag(PointerEventData eventData) {
        //当发生拖动时在拖动对象上调用
    }
    public void OnPointerClick(PointerEventData eventData) {
        //当在同一对象上按下和释放指针时调用
    }
    public void OnPointerDown(PointerEventData eventData) {
        //当指针压在对象上时调用
    }
    public void OnPointerUp(PointerEventData eventData) {
        //当指针被释放时调用(在原始按下的对象上调用)
    }
}









