Как заставить игровой процесс игнорировать нажатия на кнопку пользовательского интерфейса в Unity3D?

Я пытаюсь создать трехмерный щелчок, чтобы переместить игру в Unity3D.

Я добавил интерфейс Button (с помощью UnityEngine.UI), что я хотел бы в конечном итоге нажать, чтобы включить и выключить запуск.

Тем не менее, нажав на Button на самом деле, кажется, нажимает на сцену (в моем случае NavMeshAgent навигация) и заставляет мой плеер перемещаться в другое место.

Как можно отключить приведение лучей для нажатия кнопок пользовательского интерфейса или каким-то образом захватить его события?

Я использовал типичный код Unity3D, чтобы помочь пользователю войти в игровой процесс, такой как

if (Input.GetMouseButtonDown(0))
  {

то же самое, если я попробую подход

if( Input.touches.Length > 0 )
        {

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

и это похоже на iOS, Android и десктоп.

Кажется, это основная проблема, которая нажимает на пользовательский интерфейс (UnityEngine.UI.Button и т. д.), кажется, проваливаются в игровой процесс.

3 ответа

Решение

Относительно этого очень старого вопроса:

Как исторический вопрос: вот грубое и быстрое исправление, которое вы могли использовать в Unity много лет назад...

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

Реально, вы не можете сделать это больше, в течение нескольких лет.


Оставляя в стороне историческое быстрое исправление...

Вот как вы делаете это в Unity сегодня:

  1. Добавить raycaster (который занимает один клик), и

  2. Сделай это:

-

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

В основном, опять же, в основном, это все, что нужно сделать.

Все просто: именно так вы справляетесь с прикосновениями в Unity. Это все, что нужно сделать.

Добавьте raycaster и получите этот код.

Это выглядит легко, и это легко. Тем не менее, это может быть сложно сделать хорошо.


(Сноска 1 - полная информация: Ужасы OnPointerDown против OnBeginDrag в Unity3D)

(Сноска 2 - по историческим причинам: если ссылка все еще работает, вот оригинальное известное видео о том, как сделать "новое" касание в Unity, тогда: ссылка, часть 3.)


Путешествие Unity через сенсорные технологии было увлекательным:

  1. "Раннее единство" ... было чрезвычайно легко. Совершенно бесполезно. Не работал вообще.

  2. "Текущее" новое "Единство" ... Работает прекрасно. Очень легко, но сложно использовать в экспертной манере.

  3. "Грядущее единство" ... Около 2025 года они сделают так, что ОБА фактически будет работать и быть простой в использовании. Не задерживай дыхание.

(Ситуация не отличается от системы пользовательского интерфейса Unity. Сначала система пользовательского интерфейса была смехотворной. Теперь она великолепна, но несколько сложна в использовании экспертным способом.)


Удобный совет!

Помните! Когда у вас есть полноэкранная невидимая панель, которая содержит несколько кнопок. На самой полноэкранной невидимой панели вы должны отключить лучевое вещание! Это легко забыть:

У меня тоже была эта проблема, и я не смог найти много полезной информации по ней, вот что сработало для меня:

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;
    }
}

По сути, каждый щелчок проверяет, произошел ли щелчок над целевым объектом пользовательского интерфейса.

К сожалению, первые рекомендации мне не помогли, поэтому я просто пятью тегами всех панелей "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;
    }
Другие вопросы по тегам