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事件机制的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/346716

相关文章

JAVA线程的周期及调度机制详解

《JAVA线程的周期及调度机制详解》Java线程的生命周期包括NEW、RUNNABLE、BLOCKED、WAITING、TIMED_WAITING和TERMINATED,线程调度依赖操作系统,采用抢占... 目录Java线程的生命周期线程状态转换示例代码JAVA线程调度机制优先级设置示例注意事项JAVA线程

Java中自旋锁与CAS机制的深层关系与区别

《Java中自旋锁与CAS机制的深层关系与区别》CAS算法即比较并替换,是一种实现并发编程时常用到的算法,Java并发包中的很多类都使用了CAS算法,:本文主要介绍Java中自旋锁与CAS机制深层... 目录1. 引言2. 比较并交换 (Compare-and-Swap, CAS) 核心原理2.1 CAS

Spring Boot 集成 mybatis核心机制

《SpringBoot集成mybatis核心机制》这篇文章给大家介绍SpringBoot集成mybatis核心机制,本文结合实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值... 目录Spring Boot浅析1.依赖管理(Starter POMs)2.自动配置(AutoConfigu

Redis的安全机制详细介绍及配置方法

《Redis的安全机制详细介绍及配置方法》本文介绍Redis安全机制的配置方法,包括绑定IP地址、设置密码、保护模式、禁用危险命令、防火墙限制、TLS加密、客户端连接限制、最大内存使用和日志审计等,通... 目录1. 绑定 IP 地址2. 设置密码3. 保护模式4. 禁用危险命令5. 通过防火墙限制访问6.

JAVA实现Token自动续期机制的示例代码

《JAVA实现Token自动续期机制的示例代码》本文主要介绍了JAVA实现Token自动续期机制的示例代码,通过动态调整会话生命周期平衡安全性与用户体验,解决固定有效期Token带来的风险与不便,感兴... 目录1. 固定有效期Token的内在局限性2. 自动续期机制:兼顾安全与体验的解决方案3. 总结PS

详解Spring中REQUIRED事务的回滚机制详解

《详解Spring中REQUIRED事务的回滚机制详解》在Spring的事务管理中,REQUIRED是最常用也是默认的事务传播属性,本文就来详细的介绍一下Spring中REQUIRED事务的回滚机制,... 目录1. REQUIRED 的定义2. REQUIRED 下的回滚机制2.1 异常触发回滚2.2 回

基于Redis自动过期的流处理暂停机制

《基于Redis自动过期的流处理暂停机制》基于Redis自动过期的流处理暂停机制是一种高效、可靠且易于实现的解决方案,防止延时过大的数据影响实时处理自动恢复处理,以避免积压的数据影响实时性,下面就来详... 目录核心思路代码实现1. 初始化Redis连接和键前缀2. 接收数据时检查暂停状态3. 检测到延时过

Redis中哨兵机制和集群的区别及说明

《Redis中哨兵机制和集群的区别及说明》Redis哨兵通过主从复制实现高可用,适用于中小规模数据;集群采用分布式分片,支持动态扩展,适合大规模数据,哨兵管理简单但扩展性弱,集群性能更强但架构复杂,根... 目录一、架构设计与节点角色1. 哨兵机制(Sentinel)2. 集群(Cluster)二、数据分片

深入理解go中interface机制

《深入理解go中interface机制》本文主要介绍了深入理解go中interface机制,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学... 目录前言interface使用类型判断总结前言go的interface是一组method的集合,不

C# async await 异步编程实现机制详解

《C#asyncawait异步编程实现机制详解》async/await是C#5.0引入的语法糖,它基于**状态机(StateMachine)**模式实现,将异步方法转换为编译器生成的状态机类,本... 目录一、async/await 异步编程实现机制1.1 核心概念1.2 编译器转换过程1.3 关键组件解析