欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

[学习笔记]UGUI中UI和3D物体存在的点击响应问题

程序员文章站 2022-03-26 23:19:53
...

常见的有3种情况:

1.点击UI,后面的3D物体不需要响应

2.点击了UI,后面的3D物体同时也需要响应

3.点击了鼠标右键,在点到UI的时候不需要响应

以上几个问题,其实通过 EventSystem.current.IsPointerOverGameObject() 这个方法就能解决掉。

这个方法的含义就是判断当前鼠标是否点击到了UI,并返回布尔值。实现方式大概是这样的: 

bool IsPointerOverGameObject()
    {
        PointerEventData eventData = new PointerEventData(EventSystem.current);
        eventData.pressPosition = Input.mousePosition;
        eventData.position = Input.mousePosition;
        List<RaycastResult> results = new List<RaycastResult>();
        graphic.Raycast(eventData, results);
        return results.Count > 0; 
    }

但是这里提出一种新的方式。

我们的3D物体的点击触发事件,一般是用的OnMouseDown 这种自带的方法,

其实也可用点击UI的一套系统,

和UI的点击是一样的: 

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

public class ThreeDClick : MonoBehaviour, IPointerClickHandler
{
    MeshRenderer mesh;
    int count = 0;

    void Start()
    {
         mesh = GetComponent<MeshRenderer>();
    }

    void IPointerClickHandler.OnPointerClick(PointerEventData eventData)
    {
        if (count.Equals(0))
        {
            mesh.material.color = Color.yellow;
            count = 1;
        }
        else
        {
            mesh.material.color = Color.white;
            count = 0; 
        }
    }
}

但是UI的事件传递是经过GraphicRaycaster ,这个类只传递继承了Graphic的脚本,对于3D物体是并没有用的。

所以我们需要添加一个叫做PhysicsRaycaster 脚本。

使用同一套事件系统,就不用担心点击了UI之后,会影响后面的3D物体了。

至于第二个问题,可以这么解决:

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

public class UIClick : MonoBehaviour,IPointerClickHandler
{
    Image image;
    int count = 0;

    void Start()
    {
        image = GetComponent<Image>();
    }

    public void OnPointerClick(PointerEventData eventData)
    {
        if (count.Equals(0))
        {
            image.color = Color.blue;
            count = 1;
        }
        else
        {
            image.color = Color.red;
            count = 0;
        }

        ExecuteAll(eventData);
    }

    //再点击了UI之后还能点击3D物体
    void ExecuteAll(PointerEventData eventData)
    {
        List<RaycastResult> results = new List<RaycastResult>();
        EventSystem.current.RaycastAll(eventData, results);
        for (int i = 0; i < results.Count; i++)
        {
            if (!results[i].gameObject.Equals(this.gameObject))
            {
                ExecuteEvents.Execute(results[i].gameObject, eventData, ExecuteEvents.pointerClickHandler);
            }
        }
    }
}

就是通过EventSystem得到当前点击到的所有的物体,包括角标为0的UI 和角标为1的3D物体,遍历执行以下后面的事件。

至于第3个问题,使用IsPointerOverGameObject就能很好的解决,其实现的方式,也是判断当前点击到的物体的个数。

 

相关标签: Unity3d