Unity中UGUI事件系统是一个核心组件,它负责处理用户输入事件并将其传递给相应的UI元素。以下是关于UGUI事件系统的详细概述:
一、事件系统概述
-
定义:事件系统是一个根据输入(如鼠标、键盘、触摸等)将消息发送给对象的系统。
-
核心组件:事件系统主要由三个组件协同完成,即
Event System
、Input Module
和Raycaster
。
+ `Event System`:主要用来管理当前处于选中状态的游戏对象、当前正在使用的输入模块和射线发射器。
+ `Input Module`:主要用来处理输入、管理事件状态、将事件发送给场景中的对象。
+ `Raycaster`:用于确定鼠标指针位于哪个对象上方。Unity默认提供了三种射线发射器,分别是`Graphic Raycaster`(用于UI元素)、`Physics 2D Raycaster`(用于2D物理元素)和`Physics Raycaster`(用于3D物理元素)。
二、事件系统的工作原理
-
射线检测:通过射线检测来确定用户输入事件发生的位置,并将事件传递给最合适的UI元素。
-
事件类型:UGUI系统将UI可能触发的事件分为12个类型,这些类型对应于
EventTriggerType
枚举的12个值,如PointerEnter
、PointerExit
、PointerDown
、PointerUp
、PointerClick
等。
三、实现事件的三种方式
-
通过接口实现:Unity提供了许多事件接口,开发者可以在UI元素的脚本中实现这些接口,并在特定动作时触发对应方法。例如,实现
IDragHandler
接口可以实现UI元素的拖拽效果。 -
通过Event Trigger组件实现:为UI元素添加一个
Event Trigger
组件,并添加对应的事件类型。然后,将开发者自己实现的脚本方法绑定到Event Trigger
中,即可在指定动作时触发。 -
程序动态设置实现:通过C#代码动态地设置和绑定事件。这允许开发者在运行时根据需要更改绑定的事件。
四、EventSystem组件的常用属性和函数
-
常用属性:
-
firstSelectedGameObject
:设置默认选中的UI元素。 -
sendNavigationEvents
:是否发送导航事件。 -
pixelDragThreshold
:拖拽事件的像素阈值。 -
currentInputModule
:当前使用的输入模块。
-
-
常用函数:
-
SetSelectedGameObject(GameObject selected)
:设置当前选中的UI元素。 -
RaycastAll(PointerEventData eventData, List<RaycastResult> resultAppendList)
:执行射线检测,并将结果保存到指定的列表中。 -
UpdateModules()
:更新输入模块。
-
UGUI事件系统实践
通过Event Trigger组件手动实现拖动UI功能
1. 给目标UI添加EventTrigger组件并且添加Drag(拖动)事件
2. 给Drag 添加事件List,并挂载UIEventSys脚本到Runtime Only,选择触发事件后将要执行的函数
using UnityEngine;
namespace umbella.UIEvent
{
public class UIEventSys : MonoBehaviour
{
public void dragUITarget()
{
Debug.Log("将要对UITarget拖动");
}
}
}
3. 启动游戏,我们尝试拖动UI,虽然UI没有被我们拖动了(因为我们没有写具体逻辑),但是执行了我们自定义的拖动函数。
通过接口实现拖动UI功能(一)
UIEventDrag脚本挂载到需要移动的UI上。
UIEventDrag 脚本必须实现MonoBehaviour, IDragHandler, IInitializePotentialDragHandler, IBeginDragHandler, IEndDragHandler等接口。其中核心接口在于IDragHandler, IInitializePotentialDragHandler,否则IBeginDragHandler, IEndDragHandler 将无法执行。
using UnityEngine;
using UnityEngine.EventSystems;
public class UIEventDrag:MonoBehaviour,IDragHandler,IInitializePotentialDragHandler,IBeginDragHandler,IEndDragHandler
{
public void OnInitializePotentialDrag(PointerEventData eventData)
{
Debug.Log("初始化可能的拖动事件");
}
public void OnBeginDrag(PointerEventData eventData)
{
Debug.Log("开始拖动");
}
public void OnDrag(PointerEventData eventData)
{
Debug.Log("拖动");
RectTransform rec = GetComponent<RectTransform>(); //获取UI 中基础组件RectTransform
Vector3 pos; //申明Vector3 结构体来接收UI物体移动的世界坐标
//rec 是UI的RectTransform组件(UI移动全靠它为基础),eventData.position 鼠标移动的位置(屏幕坐标),eventData.enterEventCamera 哪个照相机照射的
// out pos 输出UI游戏物体对象 转换后的世界坐标
RectTransformUtility.ScreenPointToWorldPointInRectangle(rec, eventData.position, eventData.enterEventCamera,
out pos);
//设置UI 世界空间位置
rec.position = pos;
}
public void OnEndDrag(PointerEventData eventData)
{
Debug.Log("结束拖动");
}
}
通过接口实现拖动UI功能(二)
UIEventDrag脚本挂载到需要移动的UI上。
using UnityEngine;
using UnityEngine.EventSystems;
public class UIEventDrag:MonoBehaviour,IDragHandler,IDropHandler
{
public void OnDrag(PointerEventData eventData)
{
Debug.Log("拖动");
RectTransform rec = GetComponent<RectTransform>(); //获取UI 中基础组件RectTransform
Vector3 pos; //申明Vector3 结构体来接收UI物体移动的世界坐标
//rec 是UI的RectTransform组件(UI移动全靠它为基础),eventData.position 鼠标移动的位置(屏幕坐标),eventData.enterEventCamera 哪个照相机照射的
// out pos 输出UI游戏物体对象 转换后的世界坐标
RectTransformUtility.ScreenPointToWorldPointInRectangle(rec, eventData.position, eventData.enterEventCamera,
out pos);
//设置UI 世界空间位置
rec.position = pos;
}
public void OnDrop(PointerEventData eventData)
{
Debug.Log("UI游戏物体放下");
}
}
运行游戏
通过接口实现拖动UI功能(三)
1. 添加脚本UIEventDrag并挂载到目标UI上
using UnityEngine;
using UnityEngine.EventSystems;
public class UIEventDrag:MonoBehaviour,IDragHandler
{
public void OnDrag(PointerEventData eventData)
{
//获取UI的RectTransform组件
RectTransform rectTransform = GetComponent<RectTransform>();
//根据UI事件系统传来的参数eventData.delta 来改变 RectTransform组件锚点位置,实现拖动功能
rectTransform.anchoredPosition += eventData.delta;
Debug.Log("UI被拖动了");
}
}
2. 运行游戏
通过接口实现点击UI功能(一)
实现接口IPointerClickHandler(鼠标点击)、IPointerEnterHandler(鼠标进入)、IPointerExitHandler(鼠标移出)、IPointerDownHandler(鼠标按下)、IPointerUpHandler(鼠标松开)、UIEventClick脚本挂载到需要点击的UI上。
using UnityEngine;
using UnityEngine.EventSystems;
public class UIEventClick : MonoBehaviour,IPointerClickHandler,IPointerEnterHandler,IPointerExitHandler,IPointerDownHandler,IPointerUpHandler
{
public void OnPointerClick(PointerEventData eventData)
{
Debug.Log("鼠标点击了UI");
}
public void OnPointerEnter(PointerEventData eventData)
{
Debug.Log("鼠标进入UI");
}
public void OnPointerExit(PointerEventData eventData)
{
Debug.Log("鼠标退出UI");
}
public void OnPointerDown(PointerEventData eventData)
{
Debug.Log("鼠标按下了UI");
}
public void OnPointerUp(PointerEventData eventData)
{
Debug.Log("鼠标松开了UI");
}
}
运行游戏
通过接口实现选中UI功能(一)
1. 添加UIEventSelect脚本,该脚本实现了ISelectHandler(选定),IUpdateSelectedHandler(选中),IDeselectHandler(未选中)。
using UnityEngine;
using UnityEngine.EventSystems;
public class UIEventSelect : MonoBehaviour,ISelectHandler,IUpdateSelectedHandler,IDeselectHandler
{
public void OnSelect(BaseEventData eventData)
{
Debug.Log("选定了UI");
}
public void OnUpdateSelected(BaseEventData eventData)
{
Debug.Log("选中UI中");
}
public void OnDeselect(BaseEventData eventData)
{
Debug.Log("未选定UI");
}
}
2. 添加Selectable组件
3. 运行游戏
通过接口实现常见键盘操作UI功能(一)
1.添加脚本UIEventSysKey在目标UI上,并且添加Selectable组件、IScrollHandler(鼠标滚轮),ISubmitHandler(Enter/空格键),ICancelHandler(ECS键),IMoveHandler(方向键)
using UnityEngine;
using UnityEngine.EventSystems;
public class UIEventSysKey : MonoBehaviour,IScrollHandler,ISubmitHandler,ICancelHandler,IMoveHandler
{
public void OnScroll(PointerEventData eventData)
{
Debug.Log("滑动了鼠标滚轮");
}
public void OnSubmit(BaseEventData eventData)
{
Debug.Log("按下了Enter/空格键");
}
public void OnCancel(BaseEventData eventData)
{
Debug.Log("按下了ECS键");
}
public void OnMove(AxisEventData eventData)
{
Debug.Log("按下了方向键(WSAD、上下左右键)");
}
}
2. 运行游戏
想获取更多学习资源,可以关注公众号:脚本开发者,或者加入unity交流q群:115885644,我们一起学习,一起成长~