C# 如何在Unity3D中忽略用户界面按钮的点击?

C# 如何在Unity3D中忽略用户界面按钮的点击?,c#,unity3d,navmesh,C#,Unity3d,Navmesh,我有一个UI按钮(使用UnityEngine.UI) 但是,单击按钮似乎是在场景中单击(在我的例子中,单击导航网格) 如何解决这个问题 我一直在使用典型的Unity3D代码让用户参与游戏,比如 if (Input.GetMouseButtonDown(0)) { 如果我尝试这种方法也一样 if( Input.touches.Length > 0 ) { if ( Input.touches[0].phase == TouchPhase.Began )

我有一个UI
按钮(使用
UnityEngine.UI

但是,单击
按钮
似乎是在场景中单击(在我的例子中,单击导航网格)

如何解决这个问题

我一直在使用典型的Unity3D代码让用户参与游戏,比如

if (Input.GetMouseButtonDown(0))
  {
如果我尝试这种方法也一样

if( Input.touches.Length > 0 )
        {

        if ( Input.touches[0].phase == TouchPhase.Began )
            {
在iOS、Android和桌面上似乎也是如此

点击UI(
UnityEngine.UI.Button
等)似乎会影响游戏性,这似乎是一个基本问题。

以下是您今天在Unity中的操作方式:
  • 当然,您在层次结构中会有一个
    EventSystem
    ——只需检查一下就可以了。(例如,当您添加画布时,您会自动获得其中一个;通常,Unity项目中的每个场景都已经有一个
    EventSystem
    ,但只需检查您是否有一个。)

  • 物理光线投射器添加到相机(只需单击一次)

  • 这样做:

  • 基本上,再次基本上,这就是它的全部

    非常简单:这就是你在统一中处理接触的方式。就这些

    添加一个光线投射器,并拥有该代码

    看起来很容易,也很容易。然而,做好工作可能会很复杂


    (脚注:在团结中做拖拉的一些恐怖行为:)


    Unity的触摸技术之旅令人着迷:

  • “早期统一”。。。非常容易。毫无用处。根本不起作用

  • “当前的‘新’统一”。。。工作得很漂亮。非常简单,但很难以专家的方式使用

  • “未来的统一”。。。到2025年左右,它们将使它既能实际工作,又易于使用。不要屏住呼吸

  • (这种情况与Unity的UI系统没有什么不同。起初,UI系统很可笑。现在,它很好,但以专家的方式使用起来有些复杂。到2019年,他们将再次完全改变它。)

    (网络是一样的。起初完全是垃圾。“新”的网络相当不错,但有一些非常糟糕的选择。就在最近,他们又改变了网络。)


    方便的相关提示

    记住!当您有一个全屏不可见的面板,其中包含一些按钮时。在全屏不可见面板上,必须关闭光线投射!很容易忘记:


    作为一件历史性的事情:这里是“忽略UI”的粗略和现成的快速修复方法,您多年前在Unity中就可以使用它了

    if (Input.GetMouseButtonDown(0)) { // doesn't really work...
      if (UnityEngine.EventSystems.EventSystem.current.IsPointerOverGameObject())
          return;
      Bingo();
      }
    

    你不能再这样做了,已经有几年了。

    我也有这个问题,我找不到很多有用的信息,这就是我的工作:

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using UnityEngine.EventSystems;
    
    public class SomeClickableObject : MonoBehaviour
    {
        // keep reference to UI to detect for
        // for me this was a panel with some buttons
        public GameObject ui;
    
        void OnMouseDown()
        {
            if (!this.IsPointerOverUIObject())
            {
                // do normal OnMouseDown stuff
            }
        }
    
        private bool IsPointerOverUIObject()
        {
            // get current pointer position and raycast it
            PointerEventData eventDataCurrentPosition = new PointerEventData(EventSystem.current);
            eventDataCurrentPosition.position = new Vector2(Input.mousePosition.x, Input.mousePosition.y);
            List<RaycastResult> results = new List<RaycastResult>();
            EventSystem.current.RaycastAll(eventDataCurrentPosition, results);
    
            // check if the target is in the UI
            foreach (RaycastResult r in results) {
                bool isUIClick = r.gameObject.transform.IsChildOf(this.ui.transform); 
                if (isUIClick) {
                    return true;
                }
            }
            return false;
        }
    }
    
    使用系统集合;
    使用System.Collections.Generic;
    使用UnityEngine;
    使用UnityEngine.EventSystems;
    公共类SomeClickableObject:MonoBehavior
    {
    //保留对UI的引用以检测
    //对我来说,这是一个带有按钮的面板
    公共游戏对象界面;
    void OnMouseDown()
    {
    如果(!this.IsPointerOverUIObject())
    {
    //做些正常的事情
    }
    }
    私有bool IsPointerOverUIObject()
    {
    //获取当前指针位置并对其进行光线投射
    PointerEventData eventDataCurrentPosition=新的PointerEventData(EventSystem.current);
    eventDataCurrentPosition.position=新向量2(Input.mousePosition.x,Input.mousePosition.y);
    列表结果=新列表();
    EventSystem.current.RaycastAll(eventDataCurrentPosition,results);
    //检查目标是否在UI中
    foreach(结果中的RaycastResult r){
    bool isUIClick=r.gameObject.transform.IsChildOf(this.ui.transform);
    如果(i单击){
    返回true;
    }
    }
    返回false;
    }
    }
    

    基本上,每次单击都会检查单击是否发生在UI目标上。

    不幸的是,第一个建议对我没有帮助,因此我只使用了五个“所有面板”标记“UIPanel”,当鼠标单击时,会检查当前是否有任何面板处于活动状态

        void Update()
        { if (Input.GetMouseButtonDown(0))
            {
                if (isPanelsOn()) 
                {}//doing nothing because panels is on
                else 
                {} //doing what we need to do
             }
    }
    public static bool isPanelsOn()
        {
            GameObject[] panels = GameObject.FindGameObjectsWithTag("UIPanel");
            foreach (var panel in panels)
            {
               if (panel.activeSelf)
                {
                    return true; 
                }
            }
            return false;
        }
    

    @JoeBlow如果之前有人问过,那么请将其标记为重复,否则这似乎与主题有关(一个可能对其他人有帮助的特定编程问题)。我在发布问题之前研究了这个问题,但找不到任何内容。显然没有使用正确的关键字。谢谢你的解决方案。工作很有魅力。@Fattie-你会很友善地一步一步地描述你的解决方案,因为它最近可以实施吗?我已经在相机中添加了
    physics raycaster
    ,但是OnClick button事件仍然会传播到游戏/场景中……天哪,有50万篇文章说要使用
    EventSystem.current.IsPointerOverGameObject
    ,这没有让我想到什么地方,但这非常有效!谢谢您好@Min-对,Unity的一个巨大问题是有大量过时的文章。这很棘手。还要注意的是,他们现在正在引入另一个“全新”的UX系统:/WTH right?有点像黑客一样再次执行同样的光线投射,UI系统也会自己执行,但据我所知,没有更好的方法让EventSystem告诉您它自己的光线投射是否命中了什么。
        void Update()
        { if (Input.GetMouseButtonDown(0))
            {
                if (isPanelsOn()) 
                {}//doing nothing because panels is on
                else 
                {} //doing what we need to do
             }
    }
    public static bool isPanelsOn()
        {
            GameObject[] panels = GameObject.FindGameObjectsWithTag("UIPanel");
            foreach (var panel in panels)
            {
               if (panel.activeSelf)
                {
                    return true; 
                }
            }
            return false;
        }