Как заставить игровой процесс игнорировать нажатия на кнопку пользовательского интерфейса в 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 сегодня:
Добавить raycaster (который занимает один клик), и
Сделай это:
-
using UnityEngine.EventSystems;
public class Gameplay:MonoBehaviour, IPointerDownHandler {
public void OnPointerDown(PointerEventData eventData) {
Bingo();
}
}
В основном, опять же, в основном, это все, что нужно сделать.
Все просто: именно так вы справляетесь с прикосновениями в Unity. Это все, что нужно сделать.
Добавьте raycaster и получите этот код.
Это выглядит легко, и это легко. Тем не менее, это может быть сложно сделать хорошо.
(Сноска 1 - полная информация: Ужасы OnPointerDown против OnBeginDrag в Unity3D)
(Сноска 2 - по историческим причинам: если ссылка все еще работает, вот оригинальное известное видео о том, как сделать "новое" касание в Unity, тогда: ссылка, часть 3.)
Путешествие Unity через сенсорные технологии было увлекательным:
"Раннее единство" ... было чрезвычайно легко. Совершенно бесполезно. Не работал вообще.
"Текущее" новое "Единство" ... Работает прекрасно. Очень легко, но сложно использовать в экспертной манере.
"Грядущее единство" ... Около 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;
}