首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何检测多个/重叠的GameObjects与EventSystem?

如何检测多个/重叠的GameObjects与EventSystem?
EN

Stack Overflow用户
提问于 2017-09-13 02:50:14
回答 2查看 2.4K关注 0票数 3

我想要实现的是:牙刷应该出现在用户在BoxCollider A中单击的任何地方,包括BoxCollider B中的空间。但显然,点击B内部不会显示牙刷(OnPointerDown没有被触发)。

我尝试过的是:改变层次的顺序。

牙刷显示后,用户点击内盒对撞机A,但如果用户点击内盒对撞机B-牙刷将不会出现,这意味着OnPointerDown没有被触发。

我认为这是因为一个BoxCollider2D在另一个BoxCollider2D中的重叠。在我的例子中,B In A,我认为这是罪魁祸首,但我不知道如何解决它,或者可能有另一种方法来实现OnPointerDown

我用的是Perspective相机。但是在这个场景中,所有元素都在同一个z position中,这是0。是否有可能在每个BoxCollider2D中触发BoxCollider2D事件?

DragableObject.cs

这个剧本附在牙刷上。BoxCollider2D A也属于牙刷。

代码语言:javascript
运行
复制
public void OnPointerDown(PointerEventData eventData)
{
    Debug.Log("pointer down");

    if (GetComponent<DragableObject>() == null)
        return;

    currentObject = GetComponent<DragableObject>();

    MeshRenderer renderer = GetComponent<MeshRenderer>();

    if (ShowOnTouch)
        ShowObject();

    // Store original state
    originalPosition = transform.position;
    originalOrderLayer = renderer.sortingOrder;
    // Snap to mouse
    Vector3 newPos = cam.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, 30));
    newPos.z = 30;
    transform.position = newPos;

    if (BringToFront)
    {
        if (renderer != null)
        {
            renderer.sortingOrder = 90;
        }
    }

    ObjectActive.Invoke();
}

TargetListener.cs

这个脚本附在BoxCollider2D B上。

代码语言:javascript
运行
复制
public void OnPointerDown(PointerEventData eventData)
{
    for (int i = 0; i < Affectors.Count; i++) 
    {
        if (Affectors [i] == DragableObject.currentObject)
        {
            DragableObject.currentObject.OnEnterTarget(transform);

            ITriggerEffect[] iTrigger = GetComponents<ITriggerEffect>();

            for (int j = 0; j < iTrigger.Length; j++) 
            {
                Debug.Log("iTrigger enter");
                Debug.Log(iTrigger [j]);
                iTrigger [j].Execute(eventData, PointerState.Down);
            }
        }
        else
            continue;
    }
}

如果我点击A,牙刷就会出现,除非我点击B内部。在这里,调试日志。

这是附加到的BoxCollider2D A,它是*Toothbrush本身以及dragable.cs脚本。

更新:感谢其他人的回答,这个问题对我来说变得更清楚了。下面是BoxCollider2D A和BoxCollider2D B,它们都有大多数OnPointerHander的脚本。如何确保在各自的OnPointerHandler上触发所有BoxCollider2D

我正在处理的问题:

  1. OnPointerExit on A是在指针输入B时触发的。
  2. 如果单击B内部,OnPointerDown只在B上触发,而不是在A上触发。
EN

Stack Overflow用户

回答已采纳

发布于 2017-09-13 08:04:38

EventSystem的优点之一是事件不会通过GameObjects。第一个被击中的返回。不过,看起来你不想那样。使EventSystem返回多个GameObjects很复杂,

有两种解决办法:

1.Get .Get of EventSystem (OnPointerDownIPointerDownHandler),并使用旧的学校光线广播系统。

Physics2D.RaycastAllPhysics2D.RaycastNonAlloc可以做到这一点。出于性能原因,此示例将使用RaycastNonAlloc。这很简单。

只附加到一个GameObject(空GameObject)

代码语言:javascript
运行
复制
public class HitAll : MonoBehaviour
{
    //Detect up to 100 Objects
    const int raycastAmount = 100;
    RaycastHit2D[] result = new RaycastHit2D[raycastAmount];

    void Update()
    {
        #if UNITY_IOS || UNITY_ANDROID
        if (Input.touchCount > 0 && Input.GetTouch(0).phase == TouchPhase.Began)
        {
            checkRaycast(Input.GetTouch(0).position);
        }
        #else
        if (Input.GetMouseButtonDown(0))
        {
            checkRaycast(Input.mousePosition);
        }
        #endif
    }

    void checkRaycast(Vector2 mousePos)
    {
        Vector3 origin = Camera.main.ScreenToWorldPoint(mousePos);

        int hitCount = Physics2D.RaycastNonAlloc(origin, Vector2.zero, result, 200);
        Debug.Log(hitCount);

        for (int i = 0; i < hitCount; i++)
        {
            Debug.Log("Hit: " + result[i].collider.gameObject.name);
        }
    }
}

2.Continue使用EventSystem,但重新引发事件。

首先,使用EventSystem.current.RaycastAll抛出raycast,然后使用ExecuteEvents.Execute手动调用该事件。

用2D对撞机连接到所有的Physics2DRaycaster ,并确保连接到摄像机

代码语言:javascript
运行
复制
public class ThroughEventScript : MonoBehaviour, IPointerDownHandler
{

    public void OnPointerDown(PointerEventData eventData)
    {
        rethrowRaycast(eventData, eventData.pointerCurrentRaycast.gameObject);

        //DO STUFF WITH THE OBJECT HIT BELOW
        Debug.Log("Hit: " + eventData.pointerCurrentRaycast.gameObject.name);
    }

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

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

        //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)
            {
                //Re-simulate OnPointerDown on every Object hit
                simulateCallbackFunction(raycastResult[i].gameObject);
            }
        }
    }

    //This causes functions such as OnPointerDown to be called again
    void simulateCallbackFunction(GameObject target)
    {
        PointerEventData pointerEventData = new PointerEventData(EventSystem.current);
        //pointerEventData.ra
        RaycastResult res = new RaycastResult();
        res.gameObject = target;
        pointerEventData.pointerCurrentRaycast = res;
        ExecuteEvents.Execute(target, pointerEventData, ExecuteEvents.pointerDownHandler);
    }
}
票数 3
EN
查看全部 2 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46188071

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档