UGUI中的事件系统是处理用户输入(如鼠标点击、拖拽、键盘输入等)的核心机制。
这个系统负责检测用户的输入,并将这些输入传递给相应的UI组件进行处理。
EventSystem组件
负责管理和分发用户输入事件(如鼠标点击、触摸、键盘输入等)。每个包含UI元素的场景都应该有一个 EventSystem 组件来确保这些UI元素能够正确地响应用户的交互
它的功能如下:
事件分发:负责将用户的输入事件(如鼠标点击、触摸等)分发给相应的UI组件。它通过射线检测(Raycasting)来确定哪个UI组件被点击或触碰
输入管理:它管理用户的输入,包括鼠标、触摸屏和键盘输入。
EventSystem
可以跟踪当前的选中对象、按下对象等状态信息事件处理:处理各种类型的事件,如点击、拖动、滚动等。它通过调用UI组件上的相应接口方法来响应这些事件。
Standalone Input Module组件
专门用于处理桌面设备(如 Windows、MacOS 和 Linux)上的用户输入。
它支持鼠标、键盘和游戏手柄等多种输入设备,你可以轻松地实现用户与 UI 元素之间的交互。
它的功能如下:
鼠标输入
键盘输入
游戏手柄输入
UI事件监听接口
Raycast Target参数
在UGUI中基本上每个UI组件都会拥有这个参数,勾选后,该 UI 元素会参与 Unity 的射线检测(Event System)。
注意的是:如果多个 UI 元素重叠,射线检测会被最上层的元素拦截,下层元素可能无法触发事件。
如果想要穿透UI,或者该UI不想要被射线检测,就可以取消勾选它。
性能优化:避免为不需要交互的 UI 元素(如背景图)启用此选项,减少不必要的射线检测计算。
PointerEventData中的参数
UI事件依赖于Graphic Raycaster组件。它必须绑定Canvas,表示这个Canvas下所有UI元素支持的事件。
如何获取当前鼠标向里穿透的射线检测结果?
通过PointerEventData类中的pointerCurrentRaycast属性,来表示当前指针位置下,通过射线检测命中的 UI 元素及其相关数据。它直接关联到交互事件的触发目标(如点击、悬停、拖拽等)
获得鼠标悬停的UI信息
using UnityEngine.EventSystems;
public class HoverDetection : MonoBehaviour, IPointerEnterHandler
{
public void OnPointerEnter(PointerEventData eventData)
{
// 获取当前悬停的 UI 元素
GameObject hoveredObject = eventData.pointerCurrentRaycast.gameObject;
Debug.Log("悬停在: " + hoveredObject.name);
}
}
检测点击位置是否有UI元素
public class CustomInteraction : MonoBehaviour, IPointerClickHandler
{
public void OnPointerClick(PointerEventData eventData)
{
// 检查点击位置是否有 UI 元素
if (eventData.pointerCurrentRaycast.gameObject != null)
{
Vector2 clickPosition = eventData.pointerCurrentRaycast.screenPosition;
Debug.Log("点击位置: " + clickPosition);
}
}
}
UI相关事件
点击事件
using UnityEngine;
using UnityEngine.EventSystems;
public class ClickHandler : MonoBehaviour, IPointerClickHandler
{
public void OnPointerClick(PointerEventData eventData)
{
Debug.Log("点击了: " + gameObject.name);
// 判断左键、右键或中键点击
if (eventData.button == PointerEventData.InputButton.Left)
Debug.Log("左键点击");
else if (eventData.button == PointerEventData.InputButton.Right)
Debug.Log("右键点击");
}
}
双击事件
using UnityEngine;
using UnityEngine.EventSystems;
using System.Collections;
public class DoubleClickHandler : MonoBehaviour, IPointerClickHandler
{
private float lastClickTime;
private const float doubleClickThreshold = 0.3f; // 双击间隔阈值
public void OnPointerClick(PointerEventData eventData)
{
if (Time.time - lastClickTime < doubleClickThreshold)
{
Debug.Log("双击: " + gameObject.name);
}
lastClickTime = Time.time;
}
}
拖拽事件
using UnityEngine;
using UnityEngine.EventSystems;
public class DragHandler : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler
{
private RectTransform rectTransform;
private CanvasGroup canvasGroup;
void Awake()
{
rectTransform = GetComponent<RectTransform>();
canvasGroup = GetComponent<CanvasGroup>();
if (canvasGroup == null)
canvasGroup = gameObject.AddComponent<CanvasGroup>();
}
public void OnBeginDrag(PointerEventData eventData)
{
// 拖拽开始时,降低透明度并禁用射线检测
canvasGroup.alpha = 0.6f;
canvasGroup.blocksRaycasts = false;
}
public void OnDrag(PointerEventData eventData)
{
// 更新拖拽对象的位置(基于屏幕坐标)
rectTransform.anchoredPosition += eventData.delta / GetComponentInParent<Canvas>().scaleFactor;
}
public void OnEndDrag(PointerEventData eventData)
{
// 恢复透明度和射线检测
canvasGroup.alpha = 1f;
canvasGroup.blocksRaycasts = true;
// 检查是否拖拽到有效区域
if (eventData.pointerCurrentRaycast.gameObject == null)
Debug.Log("拖拽到无效区域");
}
}
悬停提示
using UnityEngine;
using UnityEngine.EventSystems;
public class HoverTip : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler
{
[SerializeField] private GameObject tipPanel; // 提示面板
public void OnPointerEnter(PointerEventData eventData)
{
tipPanel.SetActive(true); // 显示提示
}
public void OnPointerExit(PointerEventData eventData)
{
tipPanel.SetActive(false); // 隐藏提示
}
}
长按
using UnityEngine;
using UnityEngine.EventSystems;
using System.Collections;
public class LongPressHandler : MonoBehaviour, IPointerDownHandler, IPointerUpHandler
{
private bool isPressed;
private const float longPressDuration = 1f; // 长按判定时间
public void OnPointerDown(PointerEventData eventData)
{
isPressed = true;
StartCoroutine(CheckLongPress());
}
public void OnPointerUp(PointerEventData eventData)
{
isPressed = false;
}
private IEnumerator CheckLongPress()
{
yield return new WaitForSeconds(longPressDuration);
if (isPressed)
{
Debug.Log("长按触发: " + gameObject.name);
// 执行长按操作(如弹出菜单)
}
}
}
评论区