Unity3D 新输入系统:停止 UI 点击(或确定光标是否位于 UI 对象上)真的那么难吗?

Tom*_*Tom 13 unity-game-engine

甚至官方文档也提出了近乎疯狂的建议来解决可能是最常见的 UI/3D 交互问题之一:

如果我在光标位于 UI 按钮上方时单击,则该按钮(通过图形光线投射器)和 3D 世界(通过物理光线投射器)都将收到该事件。

官方手册: https://docs.unity3d.com/Packages/com.unity.inputsystem@1.2/manual/UISupport.html#handling-ambiguities-for-pointer-type-in ​​put本质上是说“你如何设计你的游戏所以你不需要同时需要 3D 和 UI?”。

我不敢相信这不是一个已解决的问题。但我尝试过的一切都失败了。EventSystem.current.currentSelectedGameObject是粘性的,不是悬停的。PointerData 受到保护,因此无法访问(有人提供了一种解决方法,通过从独立输入模块派生您自己的类来解决这个问题,但该解决方法显然不再有效)。IsPointerOverGameObject如果您在回调中查询旧版本,则旧版本会引发警告;如果您在 Update() 中查询旧版本,则始终为 true。

这只是心理作用。请有人告诉我,对于我所缺少的这个常见的、琐碎的问题,有一个简单、明显的解决方案。如果图形光线投射器位于 UI 元素上,那么它肯定会存储在某个地方,对吧?请?

小智 2

您的挫败感是有根据的:我发现没有让 UI 与 NewInput 一起工作的示例。我可以从 Youtube 分享更强大的 Raycaster 解决方法版本:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.InputSystem;
using UnityEngine.UI;

/* Danndx 2021 (youtube.com/danndx)
From video: youtu.be/7h1cnGggY2M
thanks - delete me! :) */
 
 
public class SCR_UiInteraction : MonoBehaviour
{
public GameObject ui_canvas;
GraphicRaycaster ui_raycaster;
 
PointerEventData click_data;
List<RaycastResult> click_results;
 
void Start()
{
    ui_raycaster = ui_canvas.GetComponent<GraphicRaycaster>();
    click_data = new PointerEventData(EventSystem.current);
    click_results = new List<RaycastResult>();
}
 
void Update()
{
    // use isPressed if you wish to ray cast every frame:
    //if(Mouse.current.leftButton.isPressed)
    
    // use wasReleasedThisFrame if you wish to ray cast just once per click:
    if(Mouse.current.leftButton.wasReleasedThisFrame)
    {
        GetUiElementsClicked();
    }
}
 
void GetUiElementsClicked()
{
    /** Get all the UI elements clicked, using the current mouse position and raycasting. **/
 
    click_data.position = Mouse.current.position.ReadValue();
    click_results.Clear();
 
    ui_raycaster.Raycast(click_data, click_results);
 
    foreach(RaycastResult result in click_results)
    {
        GameObject ui_element = result.gameObject;
 
        Debug.Log(ui_element.name);
    }
}
}
 
Run Code Online (Sandbox Code Playgroud)

那么,只需放入我的“Menusscript.cs”即可?

但作为一种模式,这对于分离UI 关注点来说是很糟糕的。我目前正在重新连接我已经在工作的每个单独关注的 PointerEventData 单击,我的问题是,为什么?我什至找不到它应该如何工作:就您而言,根本没有关于单击用户界面的官方指南,而且它不只是放在顶部。

无论如何,我还没有找到任何可以让新输入在 UI 上轻松工作的东西,并且绝对没有找到如何明智地将Menuclicks 与 Activityclicks 分开,同时保持游戏和 ui 程序集分离。

祝我们大家好运。