事件系统-输入模块
问题:为什么UI中的元素可以交互?
![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/0fb73b65096048028179e9a59c6b6c51.png)
Button Click触发过程
![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/9b63911b00dd4be88b8f78ab299b7311.png)
- 调试
![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/abc8b266668c48c38746c48770afbbb5.png)
- 点击按钮
![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/f1f842c49d9b4a6aa25df56085107274.png)
- 调用堆栈
![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/ffa291f974ef4299b9d103454c805823.png)
- Update方法
![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/48bc6994a09f40e996f3cf3b07593f1d.png)
- ProcessMouseEvent()函数来处理鼠标事件
![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/04cf9344c2f6404380c14fc7f2b9a38e.png)
protected void ProcessMouseEvent()
{
ProcessMouseEvent(0);
}
- ProcessMouseEvent(0)方法
![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/710d86656b5043328a5551537c578cda.png)
protected void ProcessMouseEvent(int id)
{
var mouseData = GetMousePointerEventData(id);
var leftButtonData = mouseData.GetButtonState(PointerEventData.InputButton.Left).eventData;
m_CurrentFocusedGameObject = leftButtonData.buttonData.pointerCurrentRaycast.gameObject;
ProcessMousePress(leftButtonData);
ProcessMove(leftButtonData.buttonData);
ProcessDrag(leftButtonData.buttonData);
ProcessMousePress(mouseData.GetButtonState(PointerEventData.InputButton.Right).eventData);
ProcessDrag(mouseData.GetButtonState(PointerEventData.InputButton.Right).eventData.buttonData);
ProcessMousePress(mouseData.GetButtonState(PointerEventData.InputButton.Middle).eventData);
ProcessDrag(mouseData.GetButtonState(PointerEventData.InputButton.Middle).eventData.buttonData);
if (!Mathf.Approximately(leftButtonData.buttonData.scrollDelta.sqrMagnitude, 0.0f))
{
var scrollHandler = ExecuteEvents.GetEventHandler<IScrollHandler>(leftButtonData.buttonData.pointerCurrentRaycast.gameObject);
ExecuteEvents.ExecuteHierarchy(scrollHandler, leftButtonData.buttonData, ExecuteEvents.scrollHandler);
}
}
- 进入到鼠标左键点击的按下事件ProcessMousePress(leftButtonData)方法里,通过调用 ReleaseMouse 方法,可以在释放鼠标时执行一些操作
![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/ad87921d79f047f18e47ecf0d79e78b2.png)
protected void ProcessMousePress(MouseButtonEventData data)
{
var pointerEvent = data.buttonData;
var currentOverGo = pointerEvent.pointerCurrentRaycast.gameObject;
if (data.PressedThisFrame())
{
pointerEvent.eligibleForClick = true;
pointerEvent.delta = Vector2.zero;
pointerEvent.dragging = false;
pointerEvent.useDragThreshold = true;
pointerEvent.pressPosition = pointerEvent.position;
pointerEvent.pointerPressRaycast = pointerEvent.pointerCurrentRaycast;
DeselectIfSelectionChanged(currentOverGo, pointerEvent);
var resetDiffTime = Time.unscaledTime - pointerEvent.clickTime;
if (resetDiffTime >= doubleClickTime)
{
pointerEvent.clickCount = 0;
}
var newPressed = ExecuteEvents.ExecuteHierarchy(currentOverGo, pointerEvent, ExecuteEvents.pointerDownHandler);
var newClick = ExecuteEvents.GetEventHandler<IPointerClickHandler>(currentOverGo);
if (newPressed == null)
newPressed = newClick;
float time = Time.unscaledTime;
if (newPressed == pointerEvent.lastPress)
{
var diffTime = time - pointerEvent.clickTime;
if (diffTime < doubleClickTime)
++pointerEvent.clickCount;
else
pointerEvent.clickCount = 1;
pointerEvent.clickTime = time;
}
else
{
pointerEvent.clickCount = 1;
}
pointerEvent.pointerPress = newPressed;
pointerEvent.rawPointerPress = currentOverGo;
pointerEvent.pointerClick = newClick;
pointerEvent.clickTime = time;
pointerEvent.pointerDrag = ExecuteEvents.GetEventHandler<IDragHandler>(currentOverGo);
if (pointerEvent.pointerDrag != null)
ExecuteEvents.Execute(pointerEvent.pointerDrag, pointerEvent, ExecuteEvents.initializePotentialDrag);
m_InputPointerEvent = pointerEvent;
}
if (data.ReleasedThisFrame())
{
ReleaseMouse(pointerEvent, currentOverGo);
}
}
- ReleaseMouse方法
![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/43e2161ef8ef499d84bb7e1f7e8ee8cd.png)
private void ReleaseMouse(PointerEventData pointerEvent, GameObject currentOverGo)
{
ExecuteEvents.Execute(pointerEvent.pointerPress, pointerEvent, ExecuteEvents.pointerUpHandler);
var pointerClickHandler = ExecuteEvents.GetEventHandler<IPointerClickHandler>(currentOverGo);
if (pointerEvent.pointerClick == pointerClickHandler && pointerEvent.eligibleForClick)
{
ExecuteEvents.Execute(pointerEvent.pointerClick, pointerEvent, ExecuteEvents.pointerClickHandler);
}
if (pointerEvent.pointerDrag != null && pointerEvent.dragging)
{
ExecuteEvents.ExecuteHierarchy(currentOverGo, pointerEvent, ExecuteEvents.dropHandler);
}
pointerEvent.eligibleForClick = false;
pointerEvent.pointerPress = null;
pointerEvent.rawPointerPress = null;
pointerEvent.pointerClick = null;
if (pointerEvent.pointerDrag != null && pointerEvent.dragging)
ExecuteEvents.Execute(pointerEvent.pointerDrag, pointerEvent, ExecuteEvents.endDragHandler);
pointerEvent.dragging = false;
pointerEvent.pointerDrag = null;
if (currentOverGo != pointerEvent.pointerEnter)
{
HandlePointerExitAndEnter(pointerEvent, null);
HandlePointerExitAndEnter(pointerEvent, currentOverGo);
}
m_InputPointerEvent = pointerEvent;
}
- ExecuteEvents.Execute方法
![Ex](https://img-blog.csdnimg.cn/direct/9aba8e013c674db0afba86dcbff340ae.png)
public static bool Execute<T>(GameObject target, BaseEventData eventData, EventFunction<T> functor) where T : IEventSystemHandler
{
var internalHandlers = ListPool<IEventSystemHandler>.Get();
GetEventList<T>(target, internalHandlers);
var internalHandlersCount = internalHandlers.Count;
for (var i = 0; i < internalHandlersCount; i++)
{
T arg;
try
{
arg = (T)internalHandlers[i];
}
catch (Exception e)
{
var temp = internalHandlers[i];
Debug.LogException(new Exception(string.Format("Type {0} expected {1} received.", typeof(T).Name, temp.GetType().Name), e));
continue;
}
try
{
functor(arg, eventData);
}
catch (Exception e)
{
Debug.LogException(e);
}
}
var handlerCount = internalHandlers.Count;
ListPool<IEventSystemHandler>.Release(internalHandlers);
return handlerCount > 0;
}
![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/0261232703db46a8a38e956951f1eddc.png)
- Excute方法,专门执行 IPointerClickHandler 接口的 OnPointerClick 方法,面向接口编程,谁实现接口,谁来做这件事情
private static void Execute(IPointerClickHandler handler, BaseEventData eventData)
{
handler.OnPointerClick(ValidateEventData<PointerEventData>(eventData));
}
- 用于处理指针点击事件(例如鼠标点击、触摸点击)
![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/a248c35506824bb69078905166946963.png)
public virtual void OnPointerClick(PointerEventData eventData)
{
if (eventData.button != PointerEventData.InputButton.Left)
return;
Press();
}
- Press方法,调用了按钮的点击事件委托 m_OnClick 的 Invoke 方法,触发了按钮的点击事件。这意味着与该按钮相关联的所有点击事件监听器都会收到通知,并执行相应的操作
![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/5fa2336675c5424f97cad9ff1cc8dc8e.png)
private void Press()
{
Debug.Log("点击按钮");
if (!IsActive() || !IsInteractable())
return;
UISystemProfilerApi.AddMarker("Button.onClick", this);
m_OnClick.Invoke();
}
![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/eaff1073a673438a8fb2d0d83196f321.png)