2017-09-18 34 views
0

我試圖實施IPointerEnterIPointerExitIPointerDownIPointerUp如何使IPointer在各自的盒子對撞機上工作?

他們都工作正常,直到他們開始重疊。

我的問題是我如何讓IPointer...在他們各自的對撞機上工作?

ABBoxCollider2DBA之內。他們兩個都有一個腳本,其實現了IPointer...以上。以下是我在這種情況下遇到的問題。

  1. 一旦在B裏面點擊鼠標,只有1個盒子會觸發IPointerDown。 (這是通過這個鏈接解決的)How to detect multiple/Overlapping GameObjects with the EventSystem?
  2. 如果我的指針(鼠標)位於A之內,並且我將指針(鼠標)移動到B,A將被觸發(IPointerExit)。我試圖實現的是AIPointerExit應該觸發它的各自對撞機。

如果我進入一個那麼「IPointerEnter」 A應該被觸發,如果進入BIPointerEnterB應該再被觸發。

enter image description here

+0

簡而言之,你不能使用內置的'IPointer ...'機制來實現你想要的。你最好的選擇是使用'Raycast'並分別檢查每一層。 –

+0

@ m.rogalski在一個UI對象上的raycast? – Programmer

+0

@編程器這個新的Unity事件系統可以在[raycasting](https://docs.unity3d.com/Manual/EventSystem.html)上工作,所以是的,我在這裏看到的唯一方法是區分哪一層被該射線擊中,檢查「下面」是否有任何圖層。 –

回答

0

我管理,爲上述問題的腳本,它可以用於簡單重疊。這意味着任何需要在另一個框內的BoxCollider2D必須是最頂層的訂單層。只需延長OverlapEventTrigger

using UnityEngine; 
using UnityEngine.EventSystems; 
using System.Collections.Generic; 
using System.Linq; 

namespace TFTM.Event 
{ 
    public enum EventExecuteType 
    { 
     PointerEnter, 
     PointerExit, 
     PointerDown, 
     PointerUp, 
     PointerDrag, 
    } 

    public abstract class OverlapEventTrigger : EventTrigger, IPointerDownHandler, IPointerUpHandler, IPointerEnterHandler, IPointerExitHandler, IDragHandler 
    { 
    public virtual void MouseDown(PointerEventData eventData){} 
    public virtual void MouseUp(PointerEventData eventData){} 
    public virtual void MouseEnter(PointerEventData eventData){} 
    public virtual void MouseExit(PointerEventData eventData){} 
    public virtual void MouseDrag(PointerEventData eventData){} 

    List<GameObject> ObjectsInCollider = new List<GameObject>(); 
    public List<RaycastResult> lastTotalRaycastResult = new List<RaycastResult>(); 

    public override void OnPointerDown(PointerEventData eventData) 
    { 
     Debug.Log("Down: " + eventData.pointerCurrentRaycast.gameObject.name); 

     MouseDown(eventData); 

     rethrowRaycast(eventData, eventData.pointerCurrentRaycast.gameObject, EventExecuteType.PointerDown); 
    } 

    public override void OnPointerUp(PointerEventData eventData) 
    { 
     Debug.Log("Up: " + eventData.pointerCurrentRaycast.gameObject.name); 

     MouseUp(eventData); 

     rethrowRaycast(eventData, eventData.pointerCurrentRaycast.gameObject, EventExecuteType.PointerUp); 
    } 

    public override void OnPointerEnter(PointerEventData eventData) 
    { 
     if (IsPointerInsideCollider(eventData) && ObjectsInCollider.Contains(gameObject)) 
      return; 

     Debug.Log("Enter: " + eventData.pointerCurrentRaycast.gameObject.name); 

     MouseEnter(eventData); 

     ObjectsInCollider.Add(gameObject); 
    } 

    public override void OnPointerExit(PointerEventData eventData) 
    { 
     //Debug.Log("Is " + gameObject.name + " inside his respective collider : " + IsPointerInsideCollider(eventData)); 

     if (IsPointerInsideCollider(eventData)) 
      return; 

     Debug.Log("Exit: " + gameObject.name); 

     MouseExit(eventData); 

     ObjectsInCollider.Remove(gameObject); 
    } 

    public override void OnDrag(PointerEventData eventData) 
    { 
     //Debug.Log("Drag: " + eventData.pointerCurrentRaycast.gameObject.name); 

     MouseDrag(eventData); 

     rethrowRaycast(eventData, eventData.pointerCurrentRaycast.gameObject, EventExecuteType.PointerDrag); 
    } 

    bool IsPointerInsideCollider(PointerEventData eventData) 
    { 
     PointerEventData pointerEventData = new PointerEventData(EventSystem.current); 
     pointerEventData.position = eventData.position; 

     List<RaycastResult> raycastResult = new List<RaycastResult>(); 

     EventSystem.current.RaycastAll(pointerEventData, raycastResult); 

     for (int i = 0; i < raycastResult.Count; i++) 
     { 
      if (raycastResult[i].gameObject == gameObject) 
      { 
       return true; 
      } 
     } 

     return false; 
    } 

    void rethrowRaycast(PointerEventData eventData, GameObject excludeGameObject, EventExecuteType eventType) 
    { 
     PointerEventData pointerEventData = new PointerEventData(EventSystem.current); 

     pointerEventData.position = eventData.pressPosition; 
     //pointerEventData.position = eventData 

     //Where to store Raycast Result 
     List<RaycastResult> raycastResult = new List<RaycastResult>(); 

     //Rethrow the raycast to include everything regardless of their Z position 
     EventSystem.current.RaycastAll(pointerEventData, raycastResult); 

     //Debug.Log("Other GameObject hit"); 
     for (int i = 0; i < raycastResult.Count; i++) 
     { 
      //Debug.Log(raycastResult[i].gameObject.name); 

      //Don't Rethrow Raycayst for the first GameObject that is hit 
      if (excludeGameObject != null && raycastResult[i].gameObject != excludeGameObject || eventType == EventExecuteType.PointerDrag) 
      { 
       //Re-simulate OnPointerDown on every Object hit 
       simulateCallbackFunction(raycastResult[i].gameObject, eventType); 
      } 
     } 
    } 

    //This causes functions such as OnPointerDown to be called again 
    void simulateCallbackFunction(GameObject target, EventExecuteType eventType) 
    { 
     PointerEventData pointerEventData = new PointerEventData(EventSystem.current); 
     //pointerEventData.ra 
     RaycastResult res = new RaycastResult(); 
     res.gameObject = target; 
     pointerEventData.pointerCurrentRaycast = res; 
     pointerEventData.position = Input.mousePosition; 

     switch (eventType) { 
      case EventExecuteType.PointerDown: 
       ExecuteEvents.Execute(target, pointerEventData, ExecuteEvents.pointerDownHandler); 
       break; 
      case EventExecuteType.PointerUp: 
       ExecuteEvents.Execute(target, pointerEventData, ExecuteEvents.pointerUpHandler); 
       break; 
      case EventExecuteType.PointerDrag: 
       ExecuteEvents.Execute(target, pointerEventData, ExecuteEvents.dragHandler); 
       break; 
      default: 
       break; 
     } 

    } 


}