本文主要是介绍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:射线投射
- GraphicRaycaster:必须挂在Canvas上,它重写了三个属性sortOrderPriority、renderOrderPriority(获取Canvas的sortingOrder和renderOrder,这在EventSystem里会作为排序依据)和eventCamera(获取canvas.worldCamera,为null则返回Camera.main),使用EventSystem.current.RaycastAll获取被照射到的对象。
- PhysicsRaycaster:必须挂在相机上,检查带碰撞的3d物体。使用Physics.RaycastAll来获取所有被照射到的对象。根据距离进行排序,然后包装成RaycastResult结构,加入到resultAppendList里面。EventSystem会将所有的Raycast的照射结果合在一起并排序,然后输入模块取到第一个结果的对象(距离最短)作为受输入事件影响的对象。
- 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事件机制的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!