目錄
一:使用
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
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/295499.html
標籤:其他