如何让游戏玩法忽略 Unity3D 中 UI 按钮的点击?

How to make gameplay ignore clicks on UI Button in Unity3D?

我有一个 UI Button(使用 UnityEngine.UI)。

但是,单击 Button 似乎是 单击 进入场景(在我的例子中单击导航网格)。

如何解决这个问题?

我一直在使用典型的 Unity3D 代码让用户进入游戏,例如

if (Input.GetMouseButtonDown(0))
  {

如果我尝试这种方法也一样

if( Input.touches.Length > 0 )
        {

        if ( Input.touches[0].phase == TouchPhase.Began )
            {

在 iOS、Android 和桌面上似乎也是如此。

点击 UI(UnityEngine.UI.Button 等)似乎是一个基本问题,但似乎无法进入游戏。

以下是您今天在 Unity 中的操作方式:

  1. 您自然会在层次结构中有一个 EventSystem - 只需检查您是否有。 (例如,当您添加一个 Canvas 时,您会自动获得其中一个;通常,Unity 项目中的每个场景都已经有一个 EventSystem,但只需检查您是否有一个。)

  2. 向相机添加 physics raycaster(只需单击一下)

  3. 这样做:

.

  using UnityEngine.EventSystems;
  public class Gameplay:MonoBehaviour, IPointerDownHandler {
   public void OnPointerDown(PointerEventData eventData) {
    Bingo();
    }
   }

基本上,再次基本上,仅此而已。

很简单:这就是您在 Unity 中处理触摸的方式。仅此而已。

添加一个光线投射器,并获得该代码。

看起来很简单,做起来很简单。然而,要做好可能会很复杂。


(脚注:在 Unity 中拖拽的一些恐怖行为:


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

  1. “早期团结”......非常容易。毫无用处。根本没用。

  2. "Current 'new' Unity" ... 效果很好。非常简单,但很难以专家的方式使用。

  3. “即将到来的未来 Unity”... 到 2025 年左右,他们将使其既实用又易于使用。不要屏住呼吸。

(情况和Unity的UI系统没什么两样。一开始UI系统很可笑,现在很好,就是有点复杂以专家的方式使用。截至 2019 年,他们将再次彻底改变它。)

(网络是一样的。起初它完全是垃圾。“新”网络 is/was 非常好,但有一些非常糟糕的选择。就在最近 2019 年,他们又改变了网络。)


实用的相关提示!

切记!当你有一个包含一些按钮的全屏 invisible 面板时。在全屏隐形面板上,您必须关闭 光线投射!很容易忘记:


作为历史事件:这是“忽略 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;
    }
}

基本上每次点击都会检查点击是否发生在 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;
    }