UGUI源码解析(一)EventSystem系统

EventSystem系统

看似名字很大,其实EventSystem处理和管理的是点击、触摸、键盘输入等事件,叫做InputEventSystem更为合适。

//系统输入模块

private List<BaseInputModule> m_SystemInputModules = new List<BaseInputModule>();

//当前输入模块

private BaseInputModule m_CurrentInputModule;

//当前选择GameObject

private GameObject m_CurrentSelected;

//处理的所有输入的EventSystem

private static List<EventSystem> m_EventSystems = new List<EventSystem>();

继承关系:

BaseInputModule抽象类

PointerInputModule抽象类

StandaloneInputModule类,面向“PC, Mac& Linux Standalone”这个平台的输入模块

TouchInputModule类,面向“IOS Android”等可触摸移动平台的输入模块

(注:在最新的2017.4UGUI源码中,TouchInputModule已经被弃用,触摸输入已经被集成到StandaloneInputModule。)

 

void Update()

  1. EventSystem会在Update里每帧执行TickModules方法,调用每一个InputModule。
  2. 遍历m_SystemInputModules,判断这些module是否支持当前平台IsModuleSupported(),并且是否可激活ShouldActivateModule()。
  3. 如果m_CurrentInputModule为空,激活InputModule,设置m_CurrentSelected,实际上就是调用eventSystem.SetSelectedGameObject,然后有把符合条件的module便赋值给m_CurrentInputModule(当前输入模块)并break。
  4. 如果m_CurrentInputModule不为空,调用每一个InputModule的Process方法,先发送事件给被选择的GameObject(m_CurrentSelected),SendUpdateEventToSelectedObject,然后先处理触摸的一些事件ProcessTouchEvents(),再处理鼠标的一些事件ProcessMouseEvent()。
  5. m_CurrentSelected大部分情况是Selectable组件(继承它的Button、Dropdown、InputField等组件)设置的。设置m_CurrentSelected,实际调用eventSystem.SetSelectedGameObject,会通过ExecuteEvents这个类对之前的对象执行一个被取消事件,且对新选中的对象执行一个被选中事件。这就是OnSelect和OnDeselect两个方法的由来。

 

EventSystem的RaycastAll方法

使用射线从相机到某个点(设为点E)投射到UI上,然后对所有投射到的对象进行排序,大致是远近排序。

RaycastAll会在PointerInputModule类的GetTouchPointerEventData和GetMousePointerEventData中调用,如果发生点击(或触摸)事件时,该事件影响的对象也会改变,通过RaycastAll方法(传入的PointerEventData的position作为点E)获得到第一个被射线照射到的对象,如果与之前的对象不同,则变更对象。(选择了新的对象,取消旧的对象)

ProcessTouchEvents()

  1. 遍历所有的inputTouch输入
  2. 调用RaycastAll方法,获得第一个被射线照射到的对象
  3. ProcessTouchPress,触发触摸事件
  4. 如果一直长按,触发ProcessMove和ProcessDrag方法。否则RemovePointerData
  5. 之后在Process()方法中,传入相应的事件接口类型,由ExecuteEvents.Execute()调用目标对象上的事件接口方法,执行事件。

ProcessMouseEvent()

  1. 获取鼠标的input输入
  2. 调用RaycastAll方法,获得第一个被射线照射到的对象
  3. ProcessMousePress,依次触发左键,右键,中键的点击事件
  4. 之后在Process()方法中,传入相应的事件接口类型,由ExecuteEvents.Execute()调用目标对象上的事件接口方法,执行事件。

 

IsPointerOverGameObject

是EventSystem类里特别常用的一个方法,用于判断是否点击在UI上,具体是在PointerInputModule中实现的,判断最后一次点击的EventData数据是否为空,不为空即在UI上。

 

EventSystem current

最后我们注意到EventSystem有一个static属性:

public static EventSystem current

get { return m_EventSystems.Count > 0 ? m_EventSystems[0] : null; }

当一个EventSystem组件OnEnable的时候会将这个对象加入到m_EventSystems。

m_EventSystems.Add(this);

OnDisable的时候会将current从m_EventSystems移除

m_EventSystems.Remove(this);

 

  • 7
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值