UI EventSystem源码解析

总流程

  1. RaycasterManager中注册了所有的Raycaster,其中有一个为GraphicRaycaster,其与Canvas配套使用,管理了自己所有勾选了raycastTarget的Graphic
  2. 每次通过InputModule点击时,会调用EventSystem遍历所有Raycaster,找到点到的所有内容,UI通过GraphicRaycaster,找到点到的所有Graphic,然后取第一个
  3. 将拿到的Graphic对应的GameObject填充到PointerEventData中,ExecuteEvents执行handler并传递PointerEventData,向上找到第一个对应的handler进行处理

RaycastManager

管理了所有的BaseRaycaster,其实就包括GraphicRaycaster、PhysicsRaycaster、Physics2DRaycaster,通过AddRaycaster(BaseRaycaster baseRaycaster)进行注册

GraphicRaycaster

与Canvas配套使用,其中Raycast(Canvas canvas, Camera eventCamera, Vector2 pointerPosition, IList<Graphic> foundGraphics, List<Graphic> results) 可以过滤Canvas中所有勾选了raycastTarget的Graphic,配合Raycast(PointerEventData eventData, List<RaycastResult> resultAppendList)获取到所有的点击Graphic

TouchInputModule

processTouchEvents()的点击事件过程,GetTouchPointerEventData(Touch input, out bool pressed, out bool released)通过touch获取到PointerDataEvent,其中pointerCurrentRaycast也在这个过程中找到点到的所有内容并取第一个,ProcessTouchPress(PointerEventData pointerEvent)时获取到pointerCurrentRaycast对应go,并且获取以其为起点向上找到第一个对应的handler进行处理,不同的handler如IPointerClickHandler,IDragHandler等

  • Tips:FakeTouches()同理,这时用的是鼠标操作

代码流程

这里以processTouchEvent()的过程为例子

  • EventSystem.Update(),本质上就是一个Monobahaviour的Update生命周期
  • TouchInputModule.Process(), 根据是否UseFakeInput()–也就是鼠标输入分别执行FakeTouches()和ProcessTouchEvents()
  • TouchInputModule.ProcessTouchEvents(),获取Touch点
  • TouchInputModule.GetTouchPointerEventData(),获取对应Touch点的PointerEventData
    • eventSystem.RaycastAll(),通过PointerEventData计算出RaycastResult,其在内部会获取RaycastManager中所有的raycasters并排序,而后通过Raycast()获取raycastResult
    • FindFirstRaycast(),获取raycastResult中的第一项,同时将其存入到pointerData.pointerCurrentRaycast中
  • TouchInputModule.ProcessTouchPress(),对上一步骤的PointerEventData进行分析,也就是获取对应PointerEventData的的go并找到对应的handler处理Event
    • Execute.GetHandlerEvent<>(),以对应的go为起点向上找第一个能处理handlerEvent的go,具体也就是重写了比如IPointerClickHandler、IDragHandler的go
    • Execute.Execute(),执行对应handler的处理回调