如何让游戏玩法忽略 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 中的操作方式:
您自然会在层次结构中有一个 EventSystem
- 只需检查您是否有。 (例如,当您添加一个 Canvas 时,您会自动获得其中一个;通常,Unity 项目中的每个场景都已经有一个 EventSystem
,但只需检查您是否有一个。)
向相机添加 physics raycaster(只需单击一下)
这样做:
.
using UnityEngine.EventSystems;
public class Gameplay:MonoBehaviour, IPointerDownHandler {
public void OnPointerDown(PointerEventData eventData) {
Bingo();
}
}
基本上,再次基本上,仅此而已。
很简单:这就是您在 Unity 中处理触摸的方式。仅此而已。
添加一个光线投射器,并获得该代码。
看起来很简单,做起来很简单。然而,要做好可能会很复杂。
(脚注:在 Unity 中拖拽的一些恐怖行为:)
Unity 的触控技术之旅令人着迷:
“早期团结”......非常容易。毫无用处。根本没用。
"Current 'new' Unity" ... 效果很好。非常简单,但很难以专家的方式使用。
“即将到来的未来 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;
}
我有一个 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 中的操作方式:
您自然会在层次结构中有一个
EventSystem
- 只需检查您是否有。 (例如,当您添加一个 Canvas 时,您会自动获得其中一个;通常,Unity 项目中的每个场景都已经有一个EventSystem
,但只需检查您是否有一个。)向相机添加 physics raycaster(只需单击一下)
这样做:
.
using UnityEngine.EventSystems;
public class Gameplay:MonoBehaviour, IPointerDownHandler {
public void OnPointerDown(PointerEventData eventData) {
Bingo();
}
}
基本上,再次基本上,仅此而已。
很简单:这就是您在 Unity 中处理触摸的方式。仅此而已。
添加一个光线投射器,并获得该代码。
看起来很简单,做起来很简单。然而,要做好可能会很复杂。
(脚注:在 Unity 中拖拽的一些恐怖行为:
Unity 的触控技术之旅令人着迷:
“早期团结”......非常容易。毫无用处。根本没用。
"Current 'new' Unity" ... 效果很好。非常简单,但很难以专家的方式使用。
“即将到来的未来 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;
}