如何确定用户的视线是否在 GUI 元素上? (HoloLens Unity.EventSystem 代码等效)

How to determine if the users gaze is on a GUI element? (HoloLens Unity.EventSystem code equivalent)

bool clickingGuiElement = false;
if (UnityEngine.EventSystems.EventSystem.current.IsPointerOverGameObject())
{
    if (UnityEngine.EventSystems.EventSystem.current.currentSelectedGameObject != null)
    {
        if (UnityEngine.EventSystems.EventSystem.current.currentSelectedGameObject
.GetComponent<CanvasRenderer>() != null)
        {
            // user is clicking on a UI element (button)
            clickingGuiElement = true;
        }
        else
            clickingGuiElement = false;
    }
    else
        clickingGuiElement = false;
}
else
    clickingGuiElement = false;

上面的代码使用了 Unity 的 EventSystem。这个小的控制结构用于处理当前被点击的对象。它完成了设置布尔值以通知程序用户是否正在单击 UI 元素的任务。在我的例子中,它主要用于按钮。使用此布尔输出可以阻止 UI 点击通过 UI 传播并与可能位于 UI.

后面的任何游戏对象交互

运行 在带有断点 and/or 的 HoloLens 上通过上面的代码打印输出结果始终相同 - 错误。该程序从未进入 HoloLens 上的第一个 if 语句。

我需要能够检测用户 airtap/clicker 在单击时输入的内容是否在 UI 元素上。如果我知道用户何时单击 UI 元素,我可以阻止它通过 UI 传播(如上所述,但同样,它在编辑器中起作用,而不在 HoloLens 上起作用) .

那么,什么可以替代在 HoloLens 上(在编辑器中)实现的相同 EventSystem 功能?

P.S。我在代码的其他部分使用 UnityEngine.EventSystems 中的 IPointerClickerHandler,它工作正常,所以我不确定为什么这个使用 EventSystems 的实现不起作用。我最好的猜测(从在编辑器中实现功能与 HoloLens 相比)是 IsPointerOverGameObject 中使用的 'Pointer' 没有利用类似于鼠标点击输入的 airtap 输入。

你的 UI 元素需要有一个碰撞器,你需要使用光线投射来检测你的 ui 元素是否被光线投射击中。在全息镜头中,我所知道的检测元素或游戏对象被击中的唯一方法是使用凝视。

编辑:在澄清问题后,您需要确保光线投射能够命中的图层只是您按钮所在的图层。

这个问题问的是检测按钮是否被点击,评论带来了对整个问题的更多理解,但问题的本质是从提问者对其他系统的体验的角度提出的,而不是从理解 Hololens 和 Unity 如何一起工作,给出你正在寻找的答案是不可能的,因为这是错误的问题。 unity 中的一切本质上都是一个游戏对象,但它们都可以同时位于场景中的不同和多个层上,您可以在 unity 中看到右上角的层。解决该问题的方法是指定按钮所在的层,并且该层不与其他游戏对象共享,这在 Unity 中不是默认行为。当您进行光线投射时,您需要忽略所有其他层,然后您将不再与按钮后面的背景对象进行交互。我包含的 link 告诉您如何做到这一点。完成后,您将像使用任何其他游戏对象一样使用连接到按钮的 airtap 事件。

这里是关于如何在 Unity 中使用图层的link。

https://answers.unity.com/questions/416919/making-raycast-ignore-multiple-layers.html

if(GazeManager.Instance.IsGazingAtObject && GazeManager.Instance.HitObject != null)
{
    Debug.Log("guiElementName: " + GazeManager.Instance.HitObject.transform.name);
}

最终没有找到等效的EventSystem代码,但是在微软提供的HoloToolkit中提供的'GazeManager'脚本中有一个简单的解决方案。

利用像上面这样的简单检查,可以确定用户的视线是否在 GUI 元素上。像这样,

// Object assignment
GameObject cursor;

// If on GUI menu control structure
if (GazeManager.Instance.IsGazingAtObject && GazeManager.Instance.HitObject != null &&
    (GazeManager.Instance.HitObject.transform.name == "icon" || 
    GazeManager.Instance.HitObject.transform.name == "guiManager"))
{
    // Scale
    cursor.transform.localScale = halfScale;

    // Move the cursor to the point where the raycast hit
    //  to display it on the gui element
    cursor.transform.position = GazeManager.Instance.HitInfo.point;

    // Enable the cursor mesh
    cursor.GetComponent<MeshRenderer>().enabled = true;
}

确实不言自明,上面的代码在用户注视 GUI 时缩放、移动和显示光标游戏对象。

在我的例子中[我使用]布尔输出[来自 EventSystem 代码试图]阻止 UI 点击通过 UI 传播并与任何 gameObjects 交互可能在UI.

后面

当注视 UI 元素时,正确使用 GazeManager 可以处理用户注视输入,而不是阻止点击。