Unity VR 开发教程 OpenXR+XR Interaction Toolkit (五) UI


此教程相关的详细教案,文档,思维导图和工程文件会分享在 Spatial XR 社区。这是一个高质量 XR 开发者社区,博主目前在内担任 XR 开发的讲师。该社区提供专人答疑、完整进阶教程、从零到一项目孵化保姆服务(包含产品上架App lab)、投资|融资对接、工程文件下载等服务。

社区链接:
SpatialXR社区:完整课程、项目下载、项目孵化宣发、答疑、投融资、专属圈子

在这里插入图片描述


往期回顾:
Unity VR 开发教程 OpenXR+XR Interaction Toolkit (一) 安装和配置
Unity VR 开发教程 OpenXR+XR Interaction Toolkit (二) 手部动画
Unity VR 开发教程 OpenXR+XR Interaction Toolkit (三) 转向和移动
Unity VR 开发教程 OpenXR+XR Interaction Toolkit (四) 传送

在 VR 的交互中,与 UI 进行交互是很常见的功能。本篇教程,我将介绍如何在 VR 世界中用射线进行 UI 的交互。


📕教程说明

使用的 Unity 版本: 2021.3.5

使用的 VR 头显: Oculus Quest 2

教程使用的 XR Interaction Toolkit 版本:2.3.2(此教程尽量考虑了向上兼容,如果有过期的地方,欢迎大家指出)

项目源码(持续更新):https://github.com/YY-nb/Unity_XRInteractionToolkit2.3.2_Demo

前期的配置:环境配置参考教程一,手部模型参考教程二。本篇教程的场景基于上一篇教程搭建的场景进行延伸。

最终实现的效果:手部射线(一开始是看不见的)对准 UI 时,会显示一条指向 UI 的射线。按下手柄的 Trigger 键,能与可交互的 UI(如 Button,Toggle,Slider 等)进行互动。

在这里插入图片描述


📕制作 World Space 模式的 UI

首先在场景中创建一个 Canvas 游戏物体。基于 VR 应用的沉浸感,其中的 UI 应该是 3D 世界中的一部分,因此我们在制作 UI 的时候要把 Canvas 组件的 Render Mode 改为 World Space

在这里插入图片描述

然后调整一下 Canvas 的大小和位置,就可以在 Canvas 上添加 UI 了。这里我就加上一个 Button,一个 Toggle 和 一个 Slider:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述


📕添加 Tracked Device Graphic Raycaster 脚本

把 Canvas 上原来的 Graphic Raycaster 组件删掉,添加 Tracked Device Graphic Raycaster 脚本。添加了这个脚本后,UI 就能被射线响应,比如被射线选中高亮。

在这里插入图片描述


📕添加 XR UI Input Module 脚本

在 EventSystem 游戏物体上添加 XR UI Input Module 脚本,并且把原先的 Standalone Input Module 脚本移除。XR UI Input Module 配合 Event System 组件,可以让 Input Action 中的动作配置作用于 VR 中的 UI,也可以用于 PC 端的键鼠调试,总的来说就是结合了 Input System,用于管理 XR 中 UI 的相关输入。

在这里插入图片描述


📕添加 UI 射线相关脚本

因为在我们的需求中,是用射线与 UI 进行交互,所以我们需要添加和射线相关的脚本。这时候我们可以联想一下我写的上一篇传送教程(Unity VR开发教程 OpenXR+XR Interaction Toolkit (四) 传送)。因为传送也有用到射线,所以我们完全可以用类似的思路实现 UI 射线,即分别在左右手的控制器上添加发送射线的相关脚本。

⭐负责 UI 射线的物体和挂载的脚本

我们沿用上一篇传送教程中的 XR Origin (因此保留了传送功能),然后分别在 LeftHand Controller 和 RightHandController 下创建 UI Ray Interactor 游戏物体:

在这里插入图片描述

模仿传送功能,在 UI Ray Interactor 物体添加上 XR Ray Interactor(Line Type 为 Straight Line,因为我们希望 UI 的射线是一条直线),Line Renderer(可以复制 TeleportController 上的 Line Renderer 组件),XR Interactor Line Visual 脚本,Sorting Group 组件(不添加该组件也能实现功能,不过官方添加 XR Ray Interactor 的时候会附带一个 Sorting Group,下面也会介绍一下 Sorting Group 的作用)。

在这里插入图片描述

在这里插入图片描述

左右手都添加了这些组件后,就能够发射一条直的射线。我们可以运行一下程序,这时候会发现两只手都会射出一条直的射线,当射线射到 UI 上时,按下手柄的 Trigger 键能被可交互的 UI (Button,Toggle,Slider)响应,比如能用射线点击按钮,拖动滑动条。

⭐为什么控制 UI 射线的物体不用添加 XR Controller

这里有些小伙伴可能会有疑问,为什么 UI Ray Interactor 不用添加 XR Controller 脚本呢?而上一篇传送教程中控制传送射线的 Teleport Interactor 物体却添加了 XR Controller 脚本,还把其中的 Enable Input Tracking 给关闭了。

我们可以看 UI Ray Interactor 的父物体 LeftHand Controller 或 RightHand Controller,在父物体上已经有了 XR Controller:

在这里插入图片描述

因为父物体 XR Controller 面板上的这些 Action 同样适用于 UI 射线操作,所以我们只需要让父物体的 XR Controller 处理输入,作为子物体的 UI Ray Interactor 无需添加额外的 XR Controller。这时候子物体的 Input Action 就会沿用父物体 XR Controller 中设置的那些 Action。

而在传送功能中,作为子物体的 Teleport Interactor 需要添加 XR Controller,是因为传送的 Select Action 和父物体的 Select Action 不一样(见下图) ,所以我们需要在子物体上额外添加一个 XR Controller,并且将 Enable Input Tracking 关闭防止追踪的冲突。

作为父物体的 LeftHand Controller:

在这里插入图片描述

作为子物体的 Teleport Interactor:

在这里插入图片描述

⭐Sorting Group 的作用

下面这段是官方文档的版本变更日志中的介绍:

Changed the Ray Interactor GameObject created through the GameObject > XR create menu to have a Sorting Group to make it render in front of UI

在创建拥有 XR Ray Interactor 的物体时,会默认添加一个 Sorting Group 组件。这个组件是 Unity UGUI 中的一个组件,每个参数具体什么意思可以查看官方文档。通过控制该组件上的参数,能够控制 UI 射线渲染在 UI 之前。

我这里就演示其中一种用法,比如我可以将 Sorting Group 的 Order in Layer 设为 5: 在这里插入图片描述
然后找到场景中的 Canvas 物体 的 Canvas 组件:

在这里插入图片描述

只要 Canvas 组件中的 Order in Layer 小于或等于 Sorting Group 中的 Order in Layer, UI 射线就会始终渲染在 UI 的前面。大家可以自行设置两个 Order in Layer 的值感受一下,如果 Canvas 组件中的 Order in Layer 大于 Sorting Group 中的 Order in Layer,那么我们是看不到 UI 射线的。

不过,即使没有添加 Sorting Group 组件,UI 射线也是会渲染在 UI 之前,只不过这个组件给了我们自定义的功能。是否需要添加这个组件就看大家的需求了。


📕过滤 UI 射线的目标

但是仍然存在一个问题,我们的 XR Interactor Line Visual 脚本规定了当 UI 射线被激活时,射线颜色为白色;未被激活时射线颜色为红色。见 XR Interactor Line Visual 的 Valid Color Gradient 和 Invalid Color Gradient:

在这里插入图片描述

但是当我们的 UI 射线射在地面上的时候仍然处于激活的状态,还会显示传送功能中射线末端的 Reticle,并且当我们按下手柄的 Grip 键,居然也会触发传送。(见下图,UI 射线射到地面上时颜色为白色,说明处于激活的状态)

在这里插入图片描述

这个问题其实和上一篇传送教程中出现的问题是一样的,此时我们拥有两种射线,一种是传送射线,被上一篇教程中我们自己写的 TeleportationController 脚本所控制;另一种是刚刚创建的 UI 射线,它使用的是默认的配置。

因为我们之前给地面添加了 Teleportation Area 脚本,默认情况下是当射线射到地面的碰撞体时,会视为选中了传送区域,然后因为负责 UI 射线的 XR Controller 中的 Select Action 默认绑定的是 XRI LeftHand/RightHand Interaction 下的 Select 动作,而 Select 动作又绑定了 “Grip 键按下” 这个操作,所以按下 Grip 键会响应到传送的功能。而且是本应该负责与 UI 交互的射线响应了传送的触发。

但我们希望的是 UI 射线只有射到 UI 上的时候才能被激活。所以我们要对能激活 UI 射线的目标做个过滤。解决办法也很简单,我们找到 LeftHand UIController 物体和 RightHand UIController 物体上挂载的 XR Ray Interactor 脚本,把 Raycast Mask 中的 Everything 改成 UI

修改前:

在这里插入图片描述

修改后:

在这里插入图片描述

现在我们再运行一下程序,这时候 UI 射线只有射到 UI 上才会变成白色,而射到地面上显示的是红色,说明只有 UI 激活了 UI 射线。

在这里插入图片描述

但是这里还可以有个优化,在当前的程序中,我们会看到手部一直射出一条有颜色的射线,即使没有指向 UI,场景中依然存在一条红色的射线。而我们可以这样改进:让射线射到 UI 上时才能显示,而射到其他地方不显示射线。


📕使射线射到 UI 上时才显示射线颜色

改进方法很简单,找到 XR Interactor Line Visual 脚本,修改 Invalid Color Gradient,我们可以把它的透明度改为 0。这样,当射线射到不是 UI 的地方时,射线就是透明的,在我们的眼中就是不显示的。

点开 Invalid Color Gradient 后,找到左上角和右上角白色的角标,点击后找到 Alpha 值,将它改成 0 就能让射线在未激活状态下处于透明状态。

修改前:

在这里插入图片描述

修改后:

在这里插入图片描述

在这里插入图片描述

现在再次运行程序,这时候只有射线射到 UI 上的时候才会看到白色的射线。


📕改变射线发射的位置

现在我们的射线是从大拇指附近射出来的,但是如果我想改变射线发射的位置呢?

其实操作也很简单,我们在手部模型下创建一个子物体作为射线发射的起始点,我这里将起始点的位置移至食指的地方,相当于让射线从食指处发出,射线发射的方向与起始点本地坐标的 z 轴方向一致

在这里插入图片描述

找到 XR Ray Interactor 脚本中的 Ray Origin Transform

在这里插入图片描述

然后将刚刚创建的射线起始点分别拖入对应的 XR Ray Interactor 脚本的 Ray Origin Transform

在这里插入图片描述

现在试着运行程序,射线就会从食指射出啦!😊

在这里插入图片描述


📕通过按下手柄菜单键控制 UI 的显示与隐藏

最近有好多小伙伴问我如何实现通过按下 VR 手柄的菜单键(一般位于左手柄上)来控制 UI 的显示和隐藏,那么我这里就介绍一种简单的做法。

⭐添加 Action

首先我们要在 XRI Default Input Actions 中配置按下手柄菜单键的 Action:

在这里插入图片描述

然后在 XRI LeftHand 中点击下图所示的 “+” 号,会新增一个 Action,我们把它命名为 Menu

在这里插入图片描述

确保右侧面板的 Action Properties 中的 Action Type 为 Button,因为我们检测的是按键是否被按下。

在这里插入图片描述

接着点击 Menu下方的这个 Binding,点击右侧面板的 Path,选择 XR Controller:

在这里插入图片描述

选择 XR Controller (LeftHand):

在这里插入图片描述

选择 Optional Controls:
在这里插入图片描述

选择 menuButton:
在这里插入图片描述

最后别忘了点击面板上方的 Save Asset 进行保存:

在这里插入图片描述

⭐脚本控制

接下来,我们需要去得到刚刚配置的 Action,并且判断 Action 是否被触发,我们可以写个脚本来控制:

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

public class UIController : MonoBehaviour
{
    public InputActionReference menu;
    public Canvas canvas;

    private void Start()
    {
        if(menu != null)
        {
            menu.action.Enable();
            menu.action.performed += ToggleMenu;
        }
        
    }

    private void ToggleMenu(InputAction.CallbackContext context)
    {
        canvas.enabled = !canvas.enabled;
    }
}

然后我把这个脚本挂载到 LeftHand Controller 物体上,并且将刚刚添加的 Menu 和场景中的 Canvas 拖拽到 面板中:

在这里插入图片描述

现在运行游戏,通过按下左手柄的菜单键就能够控制 UI 的显示和隐藏了。

  • 20
    点赞
  • 83
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 16
    评论
UnityOpenXR XR Interaction ToolkitXRIT)是一个开源的工具包,用于处理虚拟现实和增强现实应用程序中的交互。在接入HTC Vive设备时,可能会遇到手柄无法使用的问题,以下是解决这个问题的步骤: 首先,确保你已经安装了最新版本的UnityUnityXRIT插件。你可以从Unity的官方网站上下载并安装它们。 接下来,将HTC Vive设备连接到电脑,并确保它的驱动程序已正确安装,可以正常使用。 在Unity中,创建一个新的项目或打开现有项目。在项目视图中,导入XRIT插件,确保它已正确安装。 在Unity编辑器的窗口中,选择“Window”菜单,然后选择“Package Manager”。在Package Manager窗口中,搜索“XRIT”插件,并安装它。 安装完毕后,你可以在Unity编辑器的窗口中看到XRIT的工具栏和面板。 在XRIT面板中,选择“Add Input”按钮以添加新的输入设备。在下拉菜单中,选择HTC Vive手柄。这将使XRIT将Vive手柄的输入事件与Unity的输入系统进行关联。 确保Vive手柄已正确连接到电脑,并正常工作。在Unity编辑器的窗口中,选择“Play”按钮以启动项目的播放模式。 现在,你应该能够使用HTC Vive手柄进行交互了。可以测试一些基本的手柄输入,如按下按钮、移动手柄等,来确保它们在Unity中正常工作。 如果手柄仍然无法使用,可能存在其他问题,如驱动程序更新、Unity版本兼容性等。可以尝试更新驱动程序、检查Unity版本是否与XRIT插件兼容,或者在Unity的论坛或社区中寻求帮助。 总之,通过使用UnityOpenXR XR Interaction Toolkit,你应该能够解决HTC Vive手柄无法使用的问题,并实现在虚拟现实应用程序中与手柄进行交互的功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 16
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

YY-nb

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值