UI遮挡3D物体响应

问题1: 解决UI和3D物体层叠问题,只响应UI的问题

先看看当点击3D物体和UI响应事件的代码,一般点击UI使用IPointerClickHandler接口和OnPointerClick函数,点击3D物体时使用OnMouseDown函数。
点击UI代码

public class CollideUI : MonoBehaviour,IPointerClickHandler {
    private int _index;
    public void ChangeColor()
    {
        if (_index == 0)
        {
            GetComponent<Image>().color = Color.blue;
        }
        else
        {
            GetComponent<Image>().color = Color.white;
        }
        _index = _index == 0 ? 1 : 0;
    }
    public void OnPointerClick(PointerEventData eventData)
    {
        ChangeColor();
    }
}

点击3D物体代码

public class CollideCube : MonoBehaviour
{
    private int _index=0;
    private void OnMouseDown()
    {
        ChangeColor();
    }
    private void ChangeColor()
    {
        if (_index == 0)
        {
            GetComponent<MeshRenderer>().material.SetColor("_Color", Color.black);
        }
        else
        {
            GetComponent<MeshRenderer>().material.SetColor("_Color",Color.white);
        }
        _index = _index == 0 ? 1 : 0;
    }
}

但当点击后重叠3D物体的UI后响应的事件会穿透UI同时响应3D物体,事件如下所示


image.png

如何解决这一问题,我们可以在3D物体上也使用IPointerClickHandler接口以及OnPointerClick函数,但是需要在摄像机上加上Physics Raycaster组件,这样就不会出现穿透问题。
点击3D物体代码修改如下

public class CollideCube : MonoBehaviour,IPointerClickHandler
{
    private int _index=0;
    public  void ChangeColor()
    {
        if (_index == 0)
        {
            GetComponent<MeshRenderer>().material.SetColor("_Color", Color.black);
        }
        else
        {
            GetComponent<MeshRenderer>().material.SetColor("_Color",Color.white);
        }
        _index = _index == 0 ? 1 : 0;
    }
    public void OnPointerClick(PointerEventData eventData)
    {
        ChangeColor();
    }
}

如此点击叠加处UI后不会出现点击穿透问题


image.png
问题二:解决UI和3D物体的同时响应问题

除了上面3D物体使用OnMouseDown函数以外,我们想要同时响应并且同时都使用IPointerClickHandler,这样看起来比较整体。我们只需要修改点击UI方面的代码即可。代码如下

public class CollideUI : MonoBehaviour,IPointerClickHandler {
    private int _index;
    public void OnPointerClick(PointerEventData eventData)
    {
        ChangeColor();
        ExecuteAll(eventData);
    }
    public void ChangeColor()
    {
        if (_index == 0)
        {
            GetComponent<Image>().color = Color.blue;
        }
        else
        {
            GetComponent<Image>().color = Color.white;
        }
        _index = _index == 0 ? 1 : 0;
    }
    public void ExecuteAll(PointerEventData data)
    {
        List<RaycastResult> results = new List<RaycastResult>();
        //获取所有射线射中的物体并返回结果列表results
        EventSystem.current.RaycastAll(data, results);
        foreach (var result in results)
        {
            if (result.gameObject != this.gameObject)
            {
                //执行所有点击中的函数
                ExecuteEvents.Execute(result.gameObject,data,ExecuteEvents.pointerClickHandler);
            }
        }
    }
}
image.png
问题三:解决UI和鼠标点击之间的响应问题

当我有3D物体为只要点击屏幕任何地方都会响应事件的函数,那这时候当我点击UI时候这个3D物体也会同时响应。
点击到UI后同时响应

点击鼠标代码如下,挂载在3DCub。

public class ClickMouse : MonoBehaviour {
    private int _index=0;
    private void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            ChangeColor();
        }
    }
    public void ChangeColor()
    {
        if (_index == 0)
        {
            GetComponent<MeshRenderer>().material.SetColor("_Color", Color.black);
        }
        else
        {
            GetComponent<MeshRenderer>().material.SetColor("_Color", Color.white);
        }
        _index = _index == 0 ? 1 : 0;
    }
}

这时候我们想当我们点击到UI后不响应鼠标点击事件。代码如下:

public class ClickMouse : MonoBehaviour {
    private int _index=0;
    GraphicRaycaster _raycaster;
    private void Start()
    {
        _raycaster = FindObjectOfType<GraphicRaycaster>();
    }
    private void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            ChangeColor();
        }
    }
    public void ChangeColor()
    {
        if (_index == 0&& !IsUI())
        {
            GetComponent<MeshRenderer>().material.SetColor("_Color", Color.black);
        }
        else
        {
            GetComponent<MeshRenderer>().material.SetColor("_Color", Color.white);
        }
        _index = _index == 0 ? 1 : 0;
    }
    private bool IsUI()
    {
        PointerEventData data = new PointerEventData(EventSystem.current);
        data.pressPosition = Input.mousePosition;
        data.position = Input.mousePosition;
        List<RaycastResult> result = new List<RaycastResult>();
        _raycaster.Raycast(data, result);
        return result.Count > 0;
    }
}

这时候当我们点击除开UI的地方都会响应Cube的事件,当我们点击中UI后只会响应UI事件


image.png
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容