1.4 Unity3D中的eventSystem

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了1.4 Unity3D中的eventSystem相关的知识,希望对你有一定的参考价值。

参考技术A 当创建UI时,unity会自动创建eventSystem,可以看到该对象下有三个组件:EventSystem、StandaloneInputModule、TouchInputModule,后面两个组件都继承自BaseInputModule。

EventSystem组件主要负责处理输入、射线投射以及发送事件。一个场景中只能有一个EventSystem组件,并且需要BaseInputModule类型组件的协助才能工作。EventSystem在一开始的时候会把自己所属对象下的BaseInputModule类型组件加到一个内部列表,并且在每个Update周期通过接口UpdateModules接口调用这些基本输入模块的UpdateModule接口,然后BaseInputModule会在UpdateModule接口中将自己的状态修改成'Updated',之后BaseInputModule的Process接口才会被调用。

BaseInputModule是一个基类模块,负责发送输入事件(点击、拖拽、选中等)到具体对象。EventSystem下的所有输入模块都必须继承自BaseInputModule组件。StandaloneInputModule和TouchInputModule组件是系统提供的标准输入模块和触摸输入模块,我们可以通过继承BaseInputModule实现自己的输入模块。

 除了以上两个组件,还有一个很重要的组件通过EventSystem对象我们看不到,它是BaseRaycaster组件。BaseRaycaster也是一个基类,前面说的输入模块要检测到鼠标事件必须有射线投射组件才能确定目标对象。系统实现的射线投射类组件有PhysicsRaycaster, Physics2DRaycaster, GraphicRaycaster。这个模块也是可以自己继承BaseRaycaster实现个性化定制。

  总的来说,EventSystem 负责管理,BaseInputModule 负责输入,BaseRaycaster 负责确定目标对象,目标对象负责接收事件并处理,然后一个完整的事件系统就有了。

我出现过的错误:

1:在创建UI时,把eventSystem删除了,导致在使用sprite swap功能时,点击button无反应,这时要么自己创建一个点击事件,要么在路径hierarchy-create-UI-eventsystem添加一个eventsystem。

UGUI 源码解读-EventSystem

EventSystem事件系统的源码目录结构如下:大致可分为EventData、InputModules、Raycasters、EventSystem、ExecuteEvents。

EventSystem的职责:

  1. 管理和处理输入事件(InputModule)
  2. 调用Raycaster发起射线检测,获取输入事件投射到的物体
  3. 将事件发送给投射物体处理。

每个场景一般有且只有一个EventSystem,EventSystem上一般会挂一个InputModule模块。

EventData

  • BaseEventData:基础的事件信息,持有EventSystem

  • PointerEventData: 继承于BaseEventData,存储 触摸/点击/鼠标操作 事件信息,部分信息如下:

  • AxisEventData:继承于BaseEventData,移动相关的事件信息。

InputModules

  • BaseInput, 封装了触摸和鼠标的相关事件获取。

  • BaseInputModule ,所有InputModule的基类,抽象函数public abstract void Process();,持有EventSystem,EventData,BaseInput。OnEnable中调用EventSystem#UpdateModules注册输入模块。

EventSystem的Update函数中,先通过TickModules调用InputModule的UpdateModule函数,然后调用Process函数分发事件。

  • PointerInputModule,继承于BaseInputModule,封装了一些工具函数,比如GetTouchPointerEventData用于将Touch转为EventData,GetMousePointerEventData用于将鼠标点击事件转为MouseState(MouseState存放着三个鼠标按钮的事件数据)。

  • StandaloneInputModule,继承于PointerInputModule,Process函数中,先调用ProcessTouchEvents处理触摸事件,如果没有触摸事件则调用ProcessMouseEvent处理鼠标事件。

Raycasters

在事件系统中充当捕获物体的角色,管理射线,为InputModule提供GameObject

  • BaseRaycaster, 所有Raycaster的基类,OnEnable中向RaycasterManager注册,Raycast函数通过PointerEventData获取射线结果List<RaycastResult>

    public abstract void Raycast(PointerEventData eventData, List<RaycastResult> resultAppendList);
    
  • GraphicRaycaster, 见名知意,用于获取挂有Graphic脚本的GameObject,Graphic是UGUI比较重要的概念,Image、RawImage、Text等凡是需要Mesh渲染的UI都必须继承于它。

被射线检测到的结果会包装成RaycastResult返回:

什么时候会发起射线检测?

EventSystem中有一个RaycastAll函数,依次调用Raycast函数发起射线检测。

在BaseInputModule的GetTouchPointerEventDataGetMousePointerEventData函数中通过eventSystem.RaycastAll开始射线检测。

        protected PointerEventData GetTouchPointerEventData(Touch input, out bool pressed, out bool released)
        
            PointerEventData pointerData;
            var created = GetPointerData(input.fingerId, out pointerData, true);
            //....省略部分代码
            if (input.phase == TouchPhase.Canceled)
            
                pointerData.pointerCurrentRaycast = new RaycastResult();
            
            else
            
               //发起射线检测 
               eventSystem.RaycastAll(pointerData, m_RaycastResultCache);

                var raycast = FindFirstRaycast(m_RaycastResultCache);
                pointerData.pointerCurrentRaycast = raycast;
                m_RaycastResultCache.Clear();
            
            return pointerData;
        


        protected virtual MouseState GetMousePointerEventData(int id)
        
            // Populate the left button...
            PointerEventData leftData;
            var created = GetPointerData(kMouseLeftId, out leftData, true);
            //....省略部分代码
            //发起射线检测 
            eventSystem.RaycastAll(leftData, m_RaycastResultCache);
            var raycast = FindFirstRaycast(m_RaycastResultCache);
            leftData.pointerCurrentRaycast = raycast;
            m_RaycastResultCache.Clear();
            //....省略部分代码
            return m_MouseState;
        

EventSystemHandler

被射线检测到的GameObject不一定直接参与事件处理,一般会检测当前物体或者其父物体上的脚本是否实现了IEventSystemHandler接口。

public interface IPointerEnterHandler : IEventSystemHandler

    /// <summary>
    /// Use this callback to detect pointer enter events
    /// </summary>
    void OnPointerEnter(PointerEventData eventData);

接口主要分为三大类:

  • IPointerXXXHandler : 处理鼠标点击和触屏事件
  • IDragXXXXHandler:处理拖拽事件
  • IXXXHandler:处理其他如选择、取消等事件

ExecuteEvents

事件执行器,封装了事件执行相关的逻辑。

  • GetEventHandler ,用于获取实现了对应接口的GameObject

  • Execute, 获取物体身上的所有IEventSystemHandler脚本,依次执行事件函数

  • ExecuteHierarchy,逐节点寻找可执行的物体(含可用的IEventSystemHandler),触发(Execute)即停止逐根搜索。

详细执行过程可看ProcessTouchEvents和ProcessMouseEvent两个函数的逻辑。

以上是关于1.4 Unity3D中的eventSystem的主要内容,如果未能解决你的问题,请参考以下文章

Unity3d中UGUI组件精简复盘(二十)EventSystem组件与Standalone Input Moudle组件

unity3d虚拟按钮没有了

EventSyste(Unity3D)事件系统

unity3d 里面可以针对图片做点击事件吗

Unity3d从右下角用鼠标调整面板大小

Unity5.0 EventSystem事件系统的详细说明(转)