Unity3d Ugui 24 EventSystem事件机制

2023-11-05 02:10

本文主要是介绍Unity3d Ugui 24 EventSystem事件机制,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

一:使用

1:实现IEventSystemHandler接口

2:添加组件EventTrigger

3:使用Ugui封装好的组件

4:3D物体相应事件

二:源码分析

1:源码地址

2:关键脚本介绍

3:执行流程

三:按照特殊需求定义自己的事件

1:制作一个2D和3D物体可以同时生效的事件。

2:响应本身的事件并且可以穿透响应下面物体的事件。


​​​​​​​

一:使用

下面几种方式都可以添加一个事件,根据实际情况选择就行,如果需要点击的详细参数,可以选择带有BaseEventData参数的方式。

1:实现IEventSystemHandler接口

ugui提供了很多接口可以直接实现对应的接口来处理对应的事件

Pointer鼠标事件:

IPointerEnterHandler- OnPointerEnter - 当光标进入对象时调用
IPointerExitHandler - OnPointerExit - 当光标退出对象时调用
IPointerDownHandler - OnPointerDown - 按下时调用
IPointerUpHandler - OnPointerUp - 抬起时调用
IPointerClickHandler - OnPointerClick - 点击时调用

Drag拖拽事件:
IInitializePotentialDragHandler - OnInitializePotentialDrag - 在找到拖动目标时调用,可用于初始化值
IBeginDragHandler - OnBeginDrag - 拖动即将开始时在拖动对象上调用
IDragHandler - OnDrag - 发生拖动时在拖动对象上调用
IEndDragHandler - OnEndDrag - 拖动完成时在拖动对象上调用
IDropHandler - OnDrop - 在拖动完成的对象上调用,在拖拉开始的地方必须先实现IDragHandler。

在实现IBeginDragHandler、IEndDragHandler、IDropHandler 这几个接口的时候,必须先实现IDragHandler接口,不然不会响应。

滚轮滚动事件:

IScrollHandler - OnScroll - 当鼠标滚轮滚动时调用

选择事件:
IUpdateSelectedHandler - OnUpdateSelected - 选中的物体每帧触发
ISelectHandler - OnSelect -选择时调用
IDeselectHandler - OnDeselect -取消选择时调用

InputManager关联组事件(同选择组要求):
IMoveHandler - OnMove - 发生移动事件(向左、向右、向上、向下)时调用
ISubmitHandler - OnSubmit - 按下提交按钮时调用
ICancelHandler - OnCancel - 按下取消按钮时调用

下面使用点击事件来演示如何使用,其他事件一样

新建一个脚本,实现IPointerClickHandler接口然后把脚本挂在UI物体上,在点击物体时就会触发。

using UnityEngine;
using UnityEngine.EventSystems;public class ClickTest : MonoBehaviour, IPointerClickHandler
{public void OnPointerClick(PointerEventData eventData){Debug.Log("IPointerClickHandler点击了" + this.name);}
}

2:添加组件EventTrigger

a:在物体上添加EventTrigger组件,点击AddNewEventType,然后选择需要的事件类型,然后点击加号,把带有自己写的脚本的物体拖入Object,选择自己定义的函数,然后点击时就会触发。

b:可以通过代码动态绑定事件

using UnityEngine;
using UnityEngine.EventSystems;
using static UnityEngine.EventSystems.EventTrigger;public class ClickTest : MonoBehaviour
{void Start(){var tri = transform.GetComponent<EventTrigger>();if (!tri){tri= transform.gameObject.AddComponent<EventTrigger>();}TriggerEvent triEvent = new TriggerEvent();triEvent.AddListener(CustomEventTriggerAddClick);tri.triggers.Add(new EventTrigger.Entry() { eventID = EventTriggerType.PointerClick, callback = triEvent });}/// <summary>/// 代码通过EventTrigger添加事件/// </summary>/// <param name="eventData"></param>public void CustomEventTriggerAddClick(BaseEventData eventData){Debug.Log("代码通过EventTrigger添加事件点击了" + this.name);}
}

3:使用Ugui封装好的组件

a:ugui有一些组件自带了事件,例如常用的Button就有Click事件,添加一个Button,在Click点击加号添加,把带有自己写的脚本的物体拖入Object,选择自己定义的函数,然后点击时就会触发。

b:通过代码动态添加

using UnityEngine;
using UnityEngine.UI;public class ClickTest : MonoBehaviour
{void Start(){var btn = transform.GetComponent<Button>();btn.onClick.AddListener(BtnCustomClick);}public void BtnCustomClick(){Debug.Log("代码绑定Button绑定" + this.name);}
}

4:3D物体相应事件

上面是在UI物体上添加事件,3D物体可以使用吗,如果事件按照上面的流程是没有任何效果的,需要给MainCamera添加PhysicsRaycaster组件,3d物体上必须有collider。然后再按照上面的流程就可以触发对应的事件了。

二:源码分析

1:源码地址

ugui的源码已经公开,需要看源码的可以自行下载,地址:https://github.com/Unity-Technologies/uGUI

当我们在场景中创建任一UI对象后,系统都会自动创建对象EventSystem,并且该对象下有两个组件:EventSystem、StandaloneInputModule。如果是旧版的Unity还有TouchInputModule组件,两个InputModule组件都继承自BaseInputModule。

2:关键脚本介绍

Event System:事件管理器,主要负责处理输入、射线投射以及发送事件,一个场景中只能有一个EventSystem组件。获取当前最新可用的InputModule模块,每个Update通过接口UpdateModules接口调用这些基本输入模块的UpdateModule接口,然后BaseInputModule会在UpdateModule接口中将自己的状态修改成'Updated',之后BaseInputModule的Process接口才会被调用。

Standalone Inout Module:标准接收器

Touch Input Module:触屏接收器

Event Trigger:事件触发器

Graphic Raycaster:界面组件的射线检测(Canvas)

Physics/Physics2D Raycaster:场景物体的射线检测。

BaseInputModule:负责发送输入事件(点击、拖拽、选中等)到具体对象,OnEnable和OnDisable方法中,会更新EventSystem的InputModule。

BaseRaycaster:射线投射

  1. GraphicRaycaster:必须挂在Canvas上,它重写了三个属性sortOrderPriority、renderOrderPriority(获取Canvas的sortingOrder和renderOrder,这在EventSystem里会作为排序依据)和eventCamera(获取canvas.worldCamera,为null则返回Camera.main),使用EventSystem.current.RaycastAll获取被照射到的对象。
  2. PhysicsRaycaster:必须挂在相机上,检查带碰撞的3d物体。使用Physics.RaycastAll来获取所有被照射到的对象。根据距离进行排序,然后包装成RaycastResult结构,加入到resultAppendList里面。EventSystem会将所有的Raycast的照射结果合在一起并排序,然后输入模块取到第一个结果的对象(距离最短)作为受输入事件影响的对象。
  3. Physics2DRaycaster:必须挂在相机上,检查带碰撞的2d物体。使用Physics2D.RaycastAll来照射对象,并且根据SpriteRenderer组件设置结果变量作为排序依据。

RaycasterManager:是一个静态类,维护了一个BaseRaycaster类型的List,BaseRaycaster的OnEnabled与OnDisabled里将自己注册到RaycasterManager。EventSystem里也通过这个类来管理所有的射线照射器。

EventData:存储事件信息

  • BaseEventData:基础的事件信息
  • PointerEventData: 存储 触摸/点击/鼠标操作 事件信息
  • AxisEventData:移动相关的事件信息,注:拖动的操作属于PointerEventData

3:执行流程

一个完整的事件流程:通过EventSystem管理,BaseInputModule输入,BaseRaycaster确定目标对象,目标对象负责接收事件并处理。

 

 

三:按照特殊需求定义自己的事件

1:制作一个2D和3D物体可以同时生效的事件。

在MainCamera上添加PhysicsRaycaster组件就可以。

2:响应本身的事件并且可以穿透响应下面物体的事件。

例如下面的效果,添加3张图片,一个立方体,点击输出点击物体的名称。所有物体都会输出Log。可以详细的控制那个物体可以穿透,那个物体不可以穿透

先自定义一个可以穿透的事件组件

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;
public class AcrossClick : MonoBehaviour, IPointerClickHandler
{/// <summary>/// 是否可以穿透/// </summary>[SerializeField]bool canBreakThrough;/// <summary>/// 需要执行的事件/// </summary>public UnityEvent<GameObject, PointerEventData> click;public void OnPointerClick(PointerEventData eventData){click?.Invoke(this.gameObject, eventData);if (canBreakThrough){PassEvent(eventData, ExecuteEvents.pointerClickHandler);}}public void PassEvent<T>(PointerEventData eventData, ExecuteEvents.EventFunction<T> fun) where T : IEventSystemHandler{List<RaycastResult> rayResList = new List<RaycastResult>();EventSystem.current.RaycastAll(eventData, rayResList);var index = rayResList.FindIndex(r => r.gameObject == this.gameObject);//没有找到或者是点击到的最后一个物体,就不需要穿透if (index < 0 || index >= rayResList.Count - 1)return;//把事件传递给下一个物体ExecuteEvents.Execute(rayResList[index + 1].gameObject, eventData, fun);}
}

然后下一个点击以后执行的函数的脚本

using UnityEngine;
using UnityEngine.EventSystems;public class ClickTest : MonoBehaviour
{public void BtnClick(GameObject obj, PointerEventData e){Debug.Log("执行了" + obj.name);}
}

然后把ClickTest挂到一个任意物体上,把AcrossClick脚本挂在上面的3张图片一个一个立方体上。并且把canBreakThrough勾选上。把ClickTest里面的BtnClick

这篇关于Unity3d Ugui 24 EventSystem事件机制的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!


原文地址:https://blog.csdn.net/HexianWHH/article/details/119741189
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.chinasem.cn/article/346716

相关文章

Jvm sandbox mock机制的实践过程

《Jvmsandboxmock机制的实践过程》:本文主要介绍Jvmsandboxmock机制的实践过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、背景二、定义一个损坏的钟1、 Springboot工程中创建一个Clock类2、 添加一个Controller

Dubbo之SPI机制的实现原理和优势分析

《Dubbo之SPI机制的实现原理和优势分析》:本文主要介绍Dubbo之SPI机制的实现原理和优势,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Dubbo中SPI机制的实现原理和优势JDK 中的 SPI 机制解析Dubbo 中的 SPI 机制解析总结Dubbo中

Java 的 Condition 接口与等待通知机制详解

《Java的Condition接口与等待通知机制详解》在Java并发编程里,实现线程间的协作与同步是极为关键的任务,本文将深入探究Condition接口及其背后的等待通知机制,感兴趣的朋友一起看... 目录一、引言二、Condition 接口概述2.1 基本概念2.2 与 Object 类等待通知方法的区别

嵌入式Linux驱动中的异步通知机制详解

《嵌入式Linux驱动中的异步通知机制详解》:本文主要介绍嵌入式Linux驱动中的异步通知机制,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录前言一、异步通知的核心概念1. 什么是异步通知2. 异步通知的关键组件二、异步通知的实现原理三、代码示例分析1. 设备结构

JVM垃圾回收机制之GC解读

《JVM垃圾回收机制之GC解读》:本文主要介绍JVM垃圾回收机制之GC,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、死亡对象的判断算法1.1 引用计数算法1.2 可达性分析算法二、垃圾回收算法2.1 标记-清除算法2.2 复制算法2.3 标记-整理算法2.4

Python开发文字版随机事件游戏的项目实例

《Python开发文字版随机事件游戏的项目实例》随机事件游戏是一种通过生成不可预测的事件来增强游戏体验的类型,在这篇博文中,我们将使用Python开发一款文字版随机事件游戏,通过这个项目,读者不仅能够... 目录项目概述2.1 游戏概念2.2 游戏特色2.3 目标玩家群体技术选择与环境准备3.1 开发环境3

C++如何通过Qt反射机制实现数据类序列化

《C++如何通过Qt反射机制实现数据类序列化》在C++工程中经常需要使用数据类,并对数据类进行存储、打印、调试等操作,所以本文就来聊聊C++如何通过Qt反射机制实现数据类序列化吧... 目录设计预期设计思路代码实现使用方法在 C++ 工程中经常需要使用数据类,并对数据类进行存储、打印、调试等操作。由于数据类

SpringRetry重试机制之@Retryable注解与重试策略详解

《SpringRetry重试机制之@Retryable注解与重试策略详解》本文将详细介绍SpringRetry的重试机制,特别是@Retryable注解的使用及各种重试策略的配置,帮助开发者构建更加健... 目录引言一、SpringRetry基础知识二、启用SpringRetry三、@Retryable注解

SpringKafka错误处理(重试机制与死信队列)

《SpringKafka错误处理(重试机制与死信队列)》SpringKafka提供了全面的错误处理机制,通过灵活的重试策略和死信队列处理,下面就来介绍一下,具有一定的参考价值,感兴趣的可以了解一下... 目录引言一、Spring Kafka错误处理基础二、配置重试机制三、死信队列实现四、特定异常的处理策略五

C#如何动态创建Label,及动态label事件

《C#如何动态创建Label,及动态label事件》:本文主要介绍C#如何动态创建Label,及动态label事件,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录C#如何动态创建Label,及动态label事件第一点:switch中的生成我们的label事件接着,