Unity VR 开发教程 OpenXR+XR Interaction Toolkit (六)手与物品交互(触摸、抓取)

这篇具有很好参考价值的文章主要介绍了Unity VR 开发教程 OpenXR+XR Interaction Toolkit (六)手与物品交互(触摸、抓取)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


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

此教程相关的详细教案,文档,思维导图和工程文件会放入 Spatial XR 社区。这是一个高质量知识星球 XR 社区,博主目前在内担任 XR 开发的讲师。此外,该社区提供教程答疑、及时交流、进阶教程、外包、行业动态等服务。

社区链接:
Spatial XR 高级社区(知识星球)
Spatial XR 高级社区(爱发电)

Unity VR 开发教程 OpenXR+XR Interaction Toolkit (六)手与物品交互(触摸、抓取)


交互一般需要两个对象:一个是可交互的对象(Interactable),一个是发起交互的对象(Interactor,一般是玩家自己)。本系列教程中的传送功能也是交互的一种方式,可传送的地面是可交互的对象,手部发出的传送射线是发起交互的对象。而这篇教程将要介绍的是如何在 VR 世界中直接用双手与物品进行交互,此时物品是可交互的对象,手是发起交互的对象。


📕教程说明

使用的 Unity 版本: 2021.3.5

使用的 VR 头显: Oculus Quest 2

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

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

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

最终实现的效果:

Unity VR 开发教程 OpenXR+XR Interaction Toolkit (六)手与物品交互(触摸、抓取)
Unity VR 开发教程 OpenXR+XR Interaction Toolkit (六)手与物品交互(触摸、抓取)
Unity VR 开发教程 OpenXR+XR Interaction Toolkit (六)手与物品交互(触摸、抓取)


📕VR 交互的类型

VR 中的交互一般分为三种类型:

  • Hover (悬停) :一般指的是发起交互的对象停留在可交互对象的交互区域。以手与物品交互为例,假设物品表面为可交互区域,当手触摸到物品(悬停在物品的可交互区域),则视为触发了 Hover。
  • Grab(抓取):这个概念好理解,就是把物品抓起来。
  • Use(使用):“使用” 是基于 “抓取” 的。有时候我们可以继续使用正在抓取的物体,触发它的一些特性。比如抓取一把枪视为 Grab,然后按下枪的扳机发射子弹则视为 Use。

接下来我会详细讲解这三种类型的用法。那么首先我们需要拥有可交互对象和发起交互的对象,让交互的条件成立,然后再具体实现交互的类型。


📕发起交互的对象(Interactor)

⭐XR Direct Interactor 脚本

因为本教程场景中的 XR Origin 沿用了上一篇 UI 教程中的游戏物体,所以我们先回顾一下 XR Origin 目前的结构:

Unity VR 开发教程 OpenXR+XR Interaction Toolkit (六)手与物品交互(触摸、抓取)

类似的,我们很容易想到在 LeftHand Controller 和 RightHand Controller 下创建子物体,然后添加专门负责抓取的脚本,因为抓取基本上是用手柄的 Grip 键,而且绑定了“按下 Grip 键” 的 Input Action 已经添加到了父物体的 XR Controller 的 Select Action 中,所以子物体无需额外添加 XR Controller

Unity VR 开发教程 OpenXR+XR Interaction Toolkit (六)手与物品交互(触摸、抓取)

为了让双手成为发起交互的对象,我们需要用到 XR Direct Interactor 脚本。

Unity VR 开发教程 OpenXR+XR Interaction Toolkit (六)手与物品交互(触摸、抓取)

我们可以在 LeftHand Controller 和 RightHand Controller 下分别创建 Direct Interactor 子物体,然后在 Direct Interactor 上添加 XR Direct Interactor 脚本:

Unity VR 开发教程 OpenXR+XR Interaction Toolkit (六)手与物品交互(触摸、抓取)

Unity VR 开发教程 OpenXR+XR Interaction Toolkit (六)手与物品交互(触摸、抓取)

⭐添加可交互区域

XR Direct Interactor 需要一个 Trigger 类型的碰撞体,作为可交互的区域,并且这个碰撞体需要和 XR Direct Interactor 挂载到同一个游戏物体上。因此我这边直接在左手和右手的 Direct Interactor 上分别添加一个 Sphere Collider,调整 Radius,并且把 Is Trigger 勾选。那么当可交互对象进入这个可交互区域后,就可以进行交互。

Unity VR 开发教程 OpenXR+XR Interaction Toolkit (六)手与物品交互(触摸、抓取)


📕可交互的对象(Interactable)

首先我们创建一个可交互的物品,我这边用红色方块来表示。

Unity VR 开发教程 OpenXR+XR Interaction Toolkit (六)手与物品交互(触摸、抓取)

Unity VR 开发教程 OpenXR+XR Interaction Toolkit (六)手与物品交互(触摸、抓取)

⭐添加刚体

因为手与物品的交互基本上是基于物理效果的,所以我们要为可交互的物体添加刚体。

⭐XR Simple Interactable 脚本

最简单的可交互脚本就是 XR Simple Interactable,但是它没有自带抓取的功能。

我们在方块上添加 XR Simple Interactable 脚本:

Unity VR 开发教程 OpenXR+XR Interaction Toolkit (六)手与物品交互(触摸、抓取)

虽然 XR Simple Interactable 的官方文档没有说明需要添加刚体,但是实测后发现物体有了刚体后,XR Simple Interactable 脚本才会生效

另外要注意的是,挂载可交互脚本的游戏物体还需要一个碰撞体。游戏运行后,这个碰撞体会自动赋给 XR Simple Interactable 的 Colliders 数组。

Unity VR 开发教程 OpenXR+XR Interaction Toolkit (六)手与物品交互(触摸、抓取)

⭐Interactable Events

为了让 XR Simple Interactable 的效果可视化,我们可以添加几个功能:
1)当手触碰到方块时,方块的颜色发生改变。而这个功能也是 VR 交互方式中很常见的 Hover,即悬停在物品的可交互区域。
2)触碰到方块后,按下手柄 Grip 键,方块的颜色变成蓝色。
3)触碰到方块后,按住手柄的 Grip 键,再按下手柄的 Trigger 键,方块的颜色变回红色。

以上的三个功能也分别模拟了 VR 中常见的三种交互方式:悬停(Hover)、抓取(Grab)、使用(Use)。但是因为 XR Simple Interactable 脚本的局限性,我们不能真正将物品抓起来,而只能模拟 “抓取” 发生的事件。

这时候就要用到 XR Simple Interactable 脚本中的 Interactable Events,里面包含了交互时会发生的一些事件,可以看到里面有一个 Hover Entered,也就是开始悬停在可交互区域触发的事件。然后我们可以手动设置更改方块的材质,我这边想让方块被触碰后变成黄色。

Unity VR 开发教程 OpenXR+XR Interaction Toolkit (六)手与物品交互(触摸、抓取)

(也许有小伙伴会注意到 First Hover Entered。它的作用是只能某个手占用了相应的事件,比如一只手 Hover 的时候,另一个手过来 Hover 就不会触发这个事件。后面我们会看到的 First Select Entered 也是类似的道理)

然后,我们要实现的第二个和第三个功能分别对应了 Select Entered 和 Activated 这两个事件。同样地,我们在 Inspector 面板中手动绑定事件:

Unity VR 开发教程 OpenXR+XR Interaction Toolkit (六)手与物品交互(触摸、抓取)

看到 Select 和 Activate,是不是觉得有些眼熟呢?我们打开 XR Interaction Toolkit 中自带的输入配置文件 XRI Default Input Actions:

可以看到Unity VR 开发教程 OpenXR+XR Interaction Toolkit (六)手与物品交互(触摸、抓取)
XRI LeftHand Interaction 或者 XRI RightHand Interaction 下就有 Select 和 Activate。Select 动作绑定的是 “按下 Grip 键” 这个操作,Activate 动作绑定的是 “按下 Trigger 键” 这个操作。

Unity VR 开发教程 OpenXR+XR Interaction Toolkit (六)手与物品交互(触摸、抓取)

而 Interaction Events 中的 Select 和 Activate 使用的就是 XRI Default Input Actions 配置文件中的这两个动作,并且要注意的是:Activate 动作必须要以 Select 动作的发生为前提,Interactable Events 中的所有事件都是以“与可交互对象发生了交互”为前提。因此,当我们的手触碰到方块后按下手柄的 Grip 键,视为发生了 Select 动作,触发了 “方块的颜色变成蓝色” 这个事件;在手触碰到方块后按下手柄的 Grip 键的前提下,继续按下 Trigger 键,视为发生了 Activate 动作,触发了 “方块的颜色变成红色” 这个事件。

Unity VR 开发教程 OpenXR+XR Interaction Toolkit (六)手与物品交互(触摸、抓取)

这时候,也许有人会有疑问:在上一篇 UI Demo 中,我们也有用到 Activate 这个动作,作用是按下 Trigger 键与 UI 进行交互。虽然 XR Controller 中的 Select Action 绑定的是 Select 这个动作,正常来说得先按下Grip 键才能触发 Select 动作。可是实际上当 UI 射线射到 UI 上时,射线的颜色变成了白色,说明此时已经进入了选中的状态。我们为什么不需要先按下 Grip 键呢?

Unity VR 开发教程 OpenXR+XR Interaction Toolkit (六)手与物品交互(触摸、抓取)

这是因为 Canvas 上的 Tracked Device Graphic Raycaster 脚本的特性。这个脚本能让 UI 被射线响应,当射线射到 UI 上时,自动进入选中的状态,也就是触发了 Select 动作。然后在 Select 动作发生的前提下,我们按下 Trigger 键就能与 UI 进行交互。因此 UI Demo 中的 Activate 也是以 Select 为前提。


⭐XR Grab Interactable 脚本

给可交互的物体添加上这个脚本,就能实现真正的抓取。因为抓取对应的是 XRI Default Input Actions 配置文件中的 Select 动作,而 Select 动作绑定的是 “按下手柄的 Grip 键” 这个操作,所以当手部靠近可交互物体时,按下手柄的 Grip 键就能抓取物体。

Unity VR 开发教程 OpenXR+XR Interaction Toolkit (六)手与物品交互(触摸、抓取)

注:要想使用 XR Grab Interactable 脚本,必须给物体添加刚体组件。不过即使之前没有刚体,添加 XR Grab Interactable 脚本也会自动给物体加上刚体。

⚡Movement Type(Instantaneous, Kinematic,Velocity Tracking )

在 XR Grab Interactable 脚本中,比较重要的是三种 Movement Type:Instantaneous, Kinematic 和 Velocity Tracking

Unity VR 开发教程 OpenXR+XR Interaction Toolkit (六)手与物品交互(触摸、抓取)

为了以示区分,我这边创建了三个挂载 XR Grab Interactable 脚本的方块,红色方块对应 Instantaneous,黑色方块对应 Kinematic,绿色方块对应 Velocity Tracking

Unity VR 开发教程 OpenXR+XR Interaction Toolkit (六)手与物品交互(触摸、抓取)
Unity VR 开发教程 OpenXR+XR Interaction Toolkit (六)手与物品交互(触摸、抓取)

Instantaneous:
物体的移动位置和姿态完全跟随了 Interactor(手)的移动。它是通过在每一帧更新 Position 和 Rotation 进行移动,所以看上去物体跟随手部的移动是几乎没有延迟的。但是这种移动方式没有运用物理刚体的效果(即使物体上有刚体)。此时抓取的物体会穿过带有碰撞体的桌子,并且和其他刚体方块的碰撞效果也不是基于物理的。

Unity VR 开发教程 OpenXR+XR Interaction Toolkit (六)手与物品交互(触摸、抓取)

Kinematic:
通过 Kinematic Rigidbody(运动刚体)进行移动,跟随手部移动的过程中会有一些延迟。移动过程中物体不受力和碰撞的作用。所以此时物体触碰其他碰撞体不会受到反作用力,比如物体还是能穿过带有碰撞体的桌子。但是可以对其他刚体(Kinematic Rigidbody 除外)施加物理效果,比如此时移动的 Kinematic 方块能够推动其他放置在桌子上的方块。

Unity VR 开发教程 OpenXR+XR Interaction Toolkit (六)手与物品交互(触摸、抓取)

Velocity Tracking:
通过设置刚体的速度和角速度进行移动。跟随手部移动的过程中会有一些延迟。移动过程中带有刚体的物理效果,比如会和带有碰撞体的桌子发生碰撞,也可以对其他刚体产生力的效果。

Unity VR 开发教程 OpenXR+XR Interaction Toolkit (六)手与物品交互(触摸、抓取)

⚡Attach Transform 抓取点

XR Grab Interactable 脚本中有一个 Attach Transform 变量可以赋值,作为物体的抓取点。如果没有赋值,将默认以物体的 position 作为抓取点。

Unity VR 开发教程 OpenXR+XR Interaction Toolkit (六)手与物品交互(触摸、抓取)

这个变量有时候很有用。比如抓取一把枪,那么物品的抓取点应该位于枪柄上。
现在我们造一把简易的枪,来看看 Attach Transform 怎么使用,当然大家也可以用自己的模型资源。

Unity VR 开发教程 OpenXR+XR Interaction Toolkit (六)手与物品交互(触摸、抓取)

然后添加碰撞体,刚体以及 XR Grab Interactable 脚本。这里我先把 Movement Type 设为 Instantaneous。此时如果运行程序,会发现抓取枪的抓取点不是我们想要的样子。

Unity VR 开发教程 OpenXR+XR Interaction Toolkit (六)手与物品交互(触摸、抓取)

这时候,Attach Transform 就派上了用场。我们可以在枪的游戏物体下创建一个子物体,叫做 Attach Point。

Unity VR 开发教程 OpenXR+XR Interaction Toolkit (六)手与物品交互(触摸、抓取)
然后将 Attach Point 赋给 Attach Transform:

Unity VR 开发教程 OpenXR+XR Interaction Toolkit (六)手与物品交互(触摸、抓取)

接下来我们运行程序,动态调整 Attach Point 的 Position 和 Rotation,直到手能握住枪柄,复制 Attach Point 的 Transform组件,退出程序后将其粘贴至 Attach Point 原来的 Transform 组件。

Unity VR 开发教程 OpenXR+XR Interaction Toolkit (六)手与物品交互(触摸、抓取)
Unity VR 开发教程 OpenXR+XR Interaction Toolkit (六)手与物品交互(触摸、抓取)
Unity VR 开发教程 OpenXR+XR Interaction Toolkit (六)手与物品交互(触摸、抓取)

现在,抓取点的效果看起来稍微好了一点,大家也可以自行优化。但是这里还有一个问题,刚刚的 Attach Point 对应的是右手的抓取点,如果我用左手抓取枪,会发现 Attach Point 的位置是不对的。具体的解决方法我会放在下一个部分的 “优化一:左右手抓取” 进行详细说明。

值得注意的是,仅设置 Attach Transform 只是粗略地抓取。因为它在物理效果上显得不是很真实,可以看到物体和手之间还是有穿模的现象,因为我们用的是握拳的手部动画来作为抓取的手势。如果要实现精细的抓取,也就是根据不同物体的形状和大小匹配不同的抓取手势,可以参考我的这篇教程:Unity VR 开发教程 OpenXR+XR Interaction Toolkit(九)根据不同物体匹配对应的抓取手势,不过还是建议大家按顺序把我的教程看完。

关于 XR Grab Interactable 脚本的其他变量设置,大家可以参考官方文档:
https://docs.unity3d.com/Packages/com.unity.xr.interaction.toolkit@2.3/manual/xr-grab-interactable.html

⚡代码实现 Use 功能(制作简易手枪)

接着上面枪的例子,我们要怎么实现抓起枪后按下手柄 Trigger 键进行射击呢?这个功能实际上就是 VR 交互中的 Use 功能。

联想 XR Simple Interactable 和 Interactable Events 的部分,因为 XR Grab Interactable 脚本中也有一模一样的 Interactable Events,所以我们可以在 Inspector 面板中绑定 Activate 触发时的事件。不过,现在我想展示如何用代码来进行 Interactable Events 事件的绑定。

🔍核心脚本

我们创建一个脚本,叫做 GunController,把它挂载到枪的游戏物体上。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.XR.Interaction.Toolkit;

public class GunController : MonoBehaviour
{
    public GameObject bullet;
    public Transform spawnPoint;
    public float fireSpeed = 40;

    void Start()
    {
        XRGrabInteractable grabbable = GetComponent<XRGrabInteractable>();
        grabbable.activated.AddListener(FireBullet);
    }

    private void FireBullet(ActivateEventArgs arg)
    {
        GameObject spawnBullet = Instantiate(bullet,spawnPoint.position,spawnPoint.rotation);
        spawnBullet.GetComponent<Rigidbody>().velocity = spawnPoint.forward * fireSpeed;
        Destroy(spawnBullet,5);
    }
}

其中最重要的部分就是获取 XR Grab Interactable 中的 activated 事件,然后通过 AddListener 绑定事件触发的函数

🔍制作子弹(碰撞检测方式设为 Continous Dynamic)

然后我们可以创建一个子弹的 Prefab(需要刚体和碰撞体):

Unity VR 开发教程 OpenXR+XR Interaction Toolkit (六)手与物品交互(触摸、抓取)
这里有个小坑需要注意一下,就是我们最好要把子弹 Rigidbody 的 Collision Detection 设为 Continous Dynamic,否则因为子弹是高速运动的,有时候会检测不到和刚体的碰撞,造成子弹直接从物体中间穿过去。

Unity VR 开发教程 OpenXR+XR Interaction Toolkit (六)手与物品交互(触摸、抓取)

🔍制作子弹发射位置

再创建一个枪的子物体,叫做 Spawn Point,作为子弹生成的位置。该物体的 z 轴箭头方向对应子弹发射的方向。

Unity VR 开发教程 OpenXR+XR Interaction Toolkit (六)手与物品交互(触摸、抓取)

Unity VR 开发教程 OpenXR+XR Interaction Toolkit (六)手与物品交互(触摸、抓取)
然后把子弹和 Spawn Point 赋给 Gun Controller:

Unity VR 开发教程 OpenXR+XR Interaction Toolkit (六)手与物品交互(触摸、抓取)

这时候,枪的功能就制作好了。我们试着运行程序:

Unity VR 开发教程 OpenXR+XR Interaction Toolkit (六)手与物品交互(触摸、抓取)

大功告成!😊

🔍优化一:左右手抓取(判断哪只手与物体交互)

到目前为止,我们还有一个问题没有被解决,就是枪的 Attach Transform 的为止只适用于右手的抓取。我们希望左右手的抓取点都是正确的,但是枪的 XR Grab Interactable 脚本只能有一个 Attach Transform。那么我们其实可以动态地去切换左右手对应的 Attach Transform

首先,我们要准备好左右手对应的 Attach Point,作为切换用的 Attach Transform:

Unity VR 开发教程 OpenXR+XR Interaction Toolkit (六)手与物品交互(触摸、抓取)

然后,我们需要修改之前写的 GunController 脚本 ( 方法一,不推荐)

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.XR.Interaction.Toolkit;

public class GunController : MonoBehaviour
{
    public GameObject bullet;
    public Transform spawnPoint;
    public float fireSpeed = 40;

    private Transform leftHandAttachPoint;
    private Transform rightHandAttachPoint;
    private XRGrabInteractable grabbable;

    void Start()
    {
        leftHandAttachPoint = transform.Find("LeftHand Attach Point");
        rightHandAttachPoint = transform.Find("RightHand Attach Point");
        grabbable = GetComponent<XRGrabInteractable>();
        grabbable.selectEntered.AddListener(ChangeAttachTransform);
        grabbable.activated.AddListener(FireBullet);
    }

    private void ChangeAttachTransform(SelectEnterEventArgs arg)
    {
        Transform interactor = arg.interactorObject.transform; 
        if (interactor.name == "LeftHand Controller")
        {
            grabbable.attachTransform = leftHandAttachPoint;
        }
        else if (interactor.name == "RightHand Controller")
        {
            grabbable.attachTransform = rightHandAttachPoint;
        }
    }

    private void FireBullet(ActivateEventArgs arg)
    {
        GameObject spawnBullet = Instantiate(bullet,spawnPoint.position,spawnPoint.rotation); 
        spawnBullet.GetComponent<Rigidbody>().velocity = spawnPoint.forward * fireSpeed;
        Destroy(spawnBullet,5);
    }
}

核心思想就是给 XR Grab Interactable 的 Select Entered 事件绑定事件触发的函数,通过判断是哪一个 Interactor 来决定切换成哪一个 Attach Transform。

刚刚我们将左右手切换抓取的功能写在了枪的控制器中,但是这样代码的耦合性可能会比较高,因为除了枪,可能还会有其他的物体可以用左右手切换抓取。如果想要让左右手抓取的脚本更为通用,我们可以新建一个脚本继承 XR Grab Interactable (方法二):

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.XR.Interaction.Toolkit;

public class XRGrabInteractableTwoAttach : XRGrabInteractable
{
    public Transform leftAttachTransform;
    public Transform rightAttachTransform;
    protected override void OnSelectEntered(SelectEnterEventArgs args)
    {

        if(args.interactorObject.transform.CompareTag("Left Hand"))
        {
            attachTransform = leftAttachTransform;
        }
        else if(args.interactorObject.transform.CompareTag("Right Hand"))
        {
            attachTransform = rightAttachTransform;
        }
        base.OnSelectEntered(args);
    }
}

核心思想类似,我们是重写了 XR Grab Interactable 当中的 OnSelectEntered 方法,它会在 Select Entered 事件触发时被调用。

然后,我们把 Gun 上的 XR Grab Interactable 脚本替换成 XRGrabInteractableTwoAttach,而之前 GunController 当中和左右手抓取相关的代码就可以删除了。

另外,我这边将左右手 Attach Transform 的赋值改为了拖动赋值,并且用 Tag 来判断是哪一个 Interactor,所以不要忘了在编辑器中进行赋值,并且给左手和右手的 Direct Interactor 加上 Tag 。

Unity VR 开发教程 OpenXR+XR Interaction Toolkit (六)手与物品交互(触摸、抓取)
Unity VR 开发教程 OpenXR+XR Interaction Toolkit (六)手与物品交互(触摸、抓取)

Unity VR 开发教程 OpenXR+XR Interaction Toolkit (六)手与物品交互(触摸、抓取)

❗第一次抓取或第一次切换抓取位置错误解决方法(两种方法)

注:如果 XR Interaction Toolkit 的版本在 2.2 及以上,需要额外进行一些设置,否则每只手在第一次抓取或者第一次切换抓取的时候抓取点的位置是错误的下面我会介绍两种方法:

方法一

我们需要在可抓取物体 Gun 上添加 XRSingleGrabFreeTransformer 脚本:

Unity VR 开发教程 OpenXR+XR Interaction Toolkit (六)手与物品交互(触摸、抓取)

然后游戏运行时,会自动将 XR Single Grab Free Transformer 脚本添加到 XR Grab Interactable Two Attach 脚本:

Unity VR 开发教程 OpenXR+XR Interaction Toolkit (六)手与物品交互(触摸、抓取)

方法二

如果用这个方法,则不需要在可抓取物体 Gun 上添加 XR Single Grab Free Transformer 脚本,而是对 XR Grab Interactable Two Attach 脚本的代码进行修改:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.XR.Interaction.Toolkit;

public class XRGrabInteractableTwoAttach : XRGrabInteractable
{
    public Transform leftAttachTransform;
    public Transform rightAttachTransform;
     
    public override Transform GetAttachTransform(IXRInteractor interactor)
    {

        Transform i_attachTransform = null;
        if (interactor.transform.CompareTag("Left Hand"))
        {
            i_attachTransform = leftAttachTransform;
        }
        if (interactor.transform.CompareTag("Right Hand"))
        {
            i_attachTransform = rightAttachTransform;
        }
        return i_attachTransform != null ? i_attachTransform : base.GetAttachTransform(interactor);

    }
}

这个时候我们重写的是 GetAttachTransform 方法,而不是原来的 OnSelectEntered 方法。因为看不到 XRI 底层的具体实现方法,所以目前尚不清楚为什么这样改能够解决问题,不过经过测试,这种改法是奏效的,也欢迎研究出来的小伙伴和我一起探讨一下。

最终效果:

Unity VR 开发教程 OpenXR+XR Interaction Toolkit (六)手与物品交互(触摸、抓取)

🔍优化二:防止传送射线误触发远距离抓取(Interaction Layer Mask)

如果大家的项目中沿用了传送的功能,那么会发现一个 BUG:当向前推动手柄摇杆发射传送射线的时候,如果射线刚好射到可交互的物品上,这个物品会 “附着”在射线上,跟随射线移动,效果就和抓取一样,我们称这种现象为远距离抓取,它是由射线来控制抓取,这一部分我会在下一篇教程中进行详细说明。

Unity VR 开发教程 OpenXR+XR Interaction Toolkit (六)手与物品交互(触摸、抓取)

因为 XR Grab Interactable 的抓取对应的是 Select 这个动作,而激活传送射线也是对应 Select ,所以此时我们是误打误撞触发了远距离抓取,因此我们要想办法让传送射线不触发远距离抓取。实现方式也很简单,我们需要对之前传送的相关组件进行一些设置。

首先我们找到负责发射传送射线的 XR Ray Interactor 脚本,将关注点放到 Interaction Layer Mask 上。

Unity VR 开发教程 OpenXR+XR Interaction Toolkit (六)手与物品交互(触摸、抓取)

Unity VR 开发教程 OpenXR+XR Interaction Toolkit (六)手与物品交互(触摸、抓取)

Interaction Layer Mask 相当于交互的过滤器,表示交互的层级。当发起交互的对象(Interactor) 和可交互的对象(Interactable)的 Interaction Layer Mask 至少有一个是相同的,那么它们是可以被交互的。

XR Ray Interactor 作为 Interactor,它的层级是 Everything。然后我们找到作为 Interactable 的 Teleport Area,可以看到它的层级是 Default。

Unity VR 开发教程 OpenXR+XR Interaction Toolkit (六)手与物品交互(触摸、抓取)
因为 Default 包含在 Everything 中,所以满足 Interactor 和 Interactable 的 Interaction Layer Mask 至少有一个是相同的条件,即二者可以交互。

我们再看手与物品交互过程中的 XR Direct Interactor 和 XR Grab Interactable,它们的层级也分别是 Everything 和 Default。所以物品的 Default 也包含在传送射线的 Everything 中,传送的射线是能够与物品进行交互的。

那么我们可以单独为传送设置一个层级。我们点击 XR Ray Interactor 的 Interaction Layer Mask,再选择 Add Layer,我们新建一个 Teleport 层级:

Unity VR 开发教程 OpenXR+XR Interaction Toolkit (六)手与物品交互(触摸、抓取)

然后将与传送有关的 XR Ray Interactor 和 Teleport Area 的 Interaction Layer Mask 改成 Teleport:

Unity VR 开发教程 OpenXR+XR Interaction Toolkit (六)手与物品交互(触摸、抓取)

Unity VR 开发教程 OpenXR+XR Interaction Toolkit (六)手与物品交互(触摸、抓取)

然后把 XR Direct Interactor 的 Interaction Layer Mask 改为 Default,这样用于抓取的 Interactor 和 Interactable 的层级是相同的,不会对其他的交互方式产生干扰。当然,我们也可以为抓取单独设立一个 Interaction Layer Mask。重要的是搞清楚 Interaction Layer Mask 的作用。

Unity VR 开发教程 OpenXR+XR Interaction Toolkit (六)手与物品交互(触摸、抓取)

现在再次运行程序,这个 BUG 就消失啦!此时传送射线就只能和 Teleport Area 进行交互。😊

⚡其他功能一:将与物体接触的地方作为抓取点(Dynamic Attach)

我们之前介绍的抓取功能通过设置 Attach Transform,确定了物体被抓取后的位置与朝向。可以发现无论从物体上的哪个部位进行抓取,被抓取后的姿态都是相同的。

有时候,我们并不想要这种抓取方式,而是希望手能直接抓在抓取的部位上。XR Grab Interactable 脚本也提供了这个功能。

现在,我创建一个细长的 Cube,作为该功能的测试物体。

Unity VR 开发教程 OpenXR+XR Interaction Toolkit (六)手与物品交互(触摸、抓取)
添加碰撞体,刚体。然后添加 XR Grab Interactable 脚本,勾选其中的 Use Dynamic Attach

Unity VR 开发教程 OpenXR+XR Interaction Toolkit (六)手与物品交互(触摸、抓取)

勾选后会自动跳出 Match Position (匹配抓取时的 Position),Match Rotation(匹配抓取时的 Rotation),Snap To Collider(抓在物体的碰撞体上)。这些选项可以根据需求进行更改。

效果:

Unity VR 开发教程 OpenXR+XR Interaction Toolkit (六)手与物品交互(触摸、抓取)


⭐XR Tint Interactable Visual 脚本

Unity VR 开发教程 OpenXR+XR Interaction Toolkit (六)手与物品交互(触摸、抓取)

这个脚本可以挂载到可交互对象上,当发起交互的对象(Interactor)悬停(Hover)或者选中(Select 动作触发,对应 Input System 中设置的 Select 映射关系,一般和 “按下手柄 Grip 键” 进行绑定)可交互的对象时,能够暂时改变可交互对象的颜色。

调整 Tint Color 能够设置想要改变的颜色;勾选 Tint On Hover 能够在 Hover 的时候改变颜色;勾选 Tint On Selection 能够在 Select 的时候改变颜色。

Unity VR 开发教程 OpenXR+XR Interaction Toolkit (六)手与物品交互(触摸、抓取)


📕取消身体和可抓取物体的物理碰撞

因为 XR Origin 上有个 Character Controller 组件,是个碰撞体,所以玩家的身体是能够和其他碰撞体发生碰撞的。但是这个时候会有个 BUG,尤其是进行持续移动的时候,因为可抓取物体的刚体会和 Character Controller 发生物理作用,所以移动过程中将可抓取物体靠近自己的身体时会产生推力,造成诡异的移动现象。因此,我们要取消 Character Controller 和刚体的物理碰撞。

首先,我们要设置 XR Origin 和可抓取物体的 Layer

Unity VR 开发教程 OpenXR+XR Interaction Toolkit (六)手与物品交互(触摸、抓取)

我这里将 XR Origin 的 Layer 设为 Player,因为只需要设置 Character Controller 所在物体的 Layer,所以我们无需设置子物体的 Layer,因此选 No:

Unity VR 开发教程 OpenXR+XR Interaction Toolkit (六)手与物品交互(触摸、抓取)
Unity VR 开发教程 OpenXR+XR Interaction Toolkit (六)手与物品交互(触摸、抓取)

然后将所有可抓取的物体 Layer 设为 Interactable,这时候可以更改物体及其所有子物体的 Layer:

Unity VR 开发教程 OpenXR+XR Interaction Toolkit (六)手与物品交互(触摸、抓取)

Layer 设置完毕后我们打开 Unity 编辑器上方菜单栏的 Edit -> Project Settings -> Physics,找到 Layer Collision Matrix,将 Player 和 Interactable 的交叉点取消勾选: Unity VR 开发教程 OpenXR+XR Interaction Toolkit (六)手与物品交互(触摸、抓取)

现在,我们的身体就不会和可抓取物体发生物理碰撞了。


📕 XR Interaction Group

XR Interaction Toolkit 2.3 新出了一个 XR Interaction Group 组件。这个 Group 能够管理多个 Interactor,并且当其中一个 Interactor 生效时,Group 内的其他 Interactor 会暂时失效

举个例子,假如一个 XR Interaction Group 中有 Direct Interactor 和 Ray Interactor 。当 Direct Interactor 抓取了物体后,Ray Interactor 就无法发出射线。

回到本篇教程,此时我们的手部已经有了一个 Direct Interactor 和 UI Interactor,如果没有 XR Interaction Group,我们在抓取了物品后面向 UI,手部还是能够发出 UI 射线的。如果我们想要在抓取物体的时候让 UI 射线暂时失效,可以在 Left/RightHand Controller 物体上添加 XR Interaction Group 组件:

Unity VR 开发教程 OpenXR+XR Interaction Toolkit (六)手与物品交互(触摸、抓取)

然后点击两次 Starting Group Members 的 "+"号:

Unity VR 开发教程 OpenXR+XR Interaction Toolkit (六)手与物品交互(触摸、抓取)

将 Direct Interactor 物体和 UI Ray Interactor 物体拖到 Group 中 (这里需要先点击 Starting Group Members 下的 “+” 号,然后再拖物体,如果直接将物体拖入 Inspector 面板是不行的)

Unity VR 开发教程 OpenXR+XR Interaction Toolkit (六)手与物品交互(触摸、抓取)

这时候运行游戏,就能达到我们想要的效果了。

Unity VR 开发教程 OpenXR+XR Interaction Toolkit (六)手与物品交互(触摸、抓取)


📕XR Direct Interactor 脚本中的 Select Action Trigger

XR Direct Interactor 脚本中有个名叫 Select Action Trigger 的参数也很重要。

Unity VR 开发教程 OpenXR+XR Interaction Toolkit (六)手与物品交互(触摸、抓取)

它决定了 XR Controller 的 Select Action 要如何被触发。

Unity VR 开发教程 OpenXR+XR Interaction Toolkit (六)手与物品交互(触摸、抓取)

每个参数的意思可以参考官方文档:https://docs.unity3d.com/Packages/com.unity.xr.interaction.toolkit@2.3/manual/xr-direct-interactor.html

Unity VR 开发教程 OpenXR+XR Interaction Toolkit (六)手与物品交互(触摸、抓取)

但是官方的解释可能有些难懂,我这里就配合图文,讲一下我个人的理解。

首先讲一下 Toggle 和 Sticky,这两个相对而言比较好理解。我们就以抓取这个交互为例,抓取的 Select Action 绑定的是 “按下手柄抓取键” 这个动作。

如果选择了 Toggle,靠近物体按下手柄抓取键,物体会被抓在手上,但是这时候即使松开了抓取键,物体还是会被抓在手上,只有等到下一次按下抓取键,物体才会被释放。如果选择了 Sticky,靠近物体按下手柄抓取键,物体会被抓在手上,即使松开了抓取键,物体还是会被抓在手上,但是只有等到下一次按下抓取键并松开抓取键,物体才会被释放

Toggle:

Unity VR 开发教程 OpenXR+XR Interaction Toolkit (六)手与物品交互(触摸、抓取)

Sticky:

Unity VR 开发教程 OpenXR+XR Interaction Toolkit (六)手与物品交互(触摸、抓取)

接下来说一说 State 和 State Change 的区别。官方的解释看起来可能不大好理解。从实际使用体验上来看,在可抓取物体的 Select Mode 选择了 Single, 也就是只允许单手抓取的前提下,对这个物体进行左右手切换抓取,就能看出显著的区别。

Unity VR 开发教程 OpenXR+XR Interaction Toolkit (六)手与物品交互(触摸、抓取)

如果选择了 State,会有一只手无法接管另一只手的抓取权,可能出现在左手,也可能出现在右手。举个例子,可能右手柄按着抓取键将物体抓在手中的时候,左手柄按下抓取键无法接管抓取权,也就是无法切换到左手进行抓取,这种情况下只有先松开右手手柄抓取键才会进行切换抓取。

如果选择了 State Change,则可以随意切换抓取。因为推荐大家在抓取功能上使用 State Change。

State:

Unity VR 开发教程 OpenXR+XR Interaction Toolkit (六)手与物品交互(触摸、抓取)

State Change:

Unity VR 开发教程 OpenXR+XR Interaction Toolkit (六)手与物品交互(触摸、抓取)文章来源地址https://www.toymoban.com/news/detail-511046.html

到了这里,关于Unity VR 开发教程 OpenXR+XR Interaction Toolkit (六)手与物品交互(触摸、抓取)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Unity VR开发教程 OpenXR+XR Interaction Toolkit(七)射线抓取

    此教程相关的详细教案,文档,思维导图和工程文件会放入 Spatial XR 社区 。这是一个高质量知识星球 XR 社区,博主目前在内担任 XR 开发的讲师。此外,该社区提供教程答疑、及时交流、进阶教程、外包、行业动态等服务。 社区链接: Spatial XR 高级社区(知识星球) Spatial

    2023年04月08日
    浏览(36)
  • Unity VR 开发教程 OpenXR+XR Interaction Toolkit (一) 安装和配置

    此教程相关的详细教案,文档,思维导图和工程文件会放入 Spatial XR 社区 。这是一个高质量知识星球 XR 社区,博主目前在内担任 XR 开发的讲师。此外,该社区提供教程答疑、及时交流、进阶教程、外包、行业动态等服务。 社区链接: Spatial XR 高级社区(知识星球) Spatial

    2024年02月11日
    浏览(33)
  • Unity VR 开发教程 OpenXR+XR Interaction Toolkit (三) 转向和移动

    此教程相关的详细教案,文档,思维导图和工程文件会放入 Spatial XR 社区 。这是一个高质量知识星球 XR 社区,博主目前在内担任 XR 开发的讲师。此外,该社区提供教程答疑、及时交流、进阶教程、外包、行业动态等服务。 社区链接: Spatial XR 高级社区(知识星球) Spatial

    2024年02月11日
    浏览(49)
  • Unity VR 开发教程 OpenXR+XR Interaction Toolkit(八)手指触控 Poke Interaction

    此教程相关的详细教案,文档,思维导图和工程文件会放入 Spatial XR 社区 。这是一个高质量知识星球 XR 社区,博主目前在内担任 XR 开发的讲师。此外,该社区提供教程答疑、及时交流、进阶教程、外包、行业动态等服务。 社区链接: Spatial XR 高级社区(知识星球) Spatial

    2024年02月12日
    浏览(39)
  • Unity VR 开发教程 OpenXR+XR Interaction Toolkit(九)根据不同物体匹配对应的抓取手势

    此教程相关的详细教案,文档,思维导图和工程文件会放入 Spatial XR 社区 。这是一个高质量知识星球 XR 社区,博主目前在内担任 XR 开发的讲师。此外,该社区提供教程答疑、及时交流、进阶教程、外包、行业动态等服务。 社区链接: Spatial XR 高级社区(知识星球) Spatial

    2024年02月16日
    浏览(35)
  • Unity VR 开发教程 OpenXR+XR Interaction Toolkit 番外(一)用 Grip 键, Trigger 键和摇杆控制手部动画

    此教程相关的详细教案,文档,思维导图和工程文件会放入 Spatial XR 社区 。这是一个高质量知识星球 XR 社区,博主目前在内担任 XR 开发的讲师。此外,该社区提供教程答疑、及时交流、进阶教程、外包、行业动态等服务。 社区链接: Spatial XR 高级社区(知识星球) Spatial

    2024年02月12日
    浏览(34)
  • Unity VR开发教程 OpenXR+XR Interaction Toolkit 番外(一)用 Grip 键, Trigger 键和摇杆控制手部动画

    此教程相关的详细教案,文档,思维导图和工程文件会放入 Spatial XR 社区 。这是一个高质量知识星球 XR 社区,博主目前在内担任 XR 开发的讲师。此外,该社区提供教程答疑、及时交流、进阶教程、外包、行业动态等服务。 社区链接: Spatial XR 高级社区(知识星球) Spatial

    2024年02月07日
    浏览(57)
  • Unity之OpenXR+XR Interaction Toolkit实现 监听VR手柄按键

    当我们接入XR Interaction Toolkit之后,我们可以很方便的做不同VR设备的适配,这在很大程度上提升了我们的开发效率,我们除了通过射线和物体交互之外,偶尔我们也会希望监听手柄上的部分按键的点击事件,今天我们就来实现如何监听VR手柄的按钮事件。 我们需要准备好Uni

    2024年02月05日
    浏览(59)
  • Unity之OpenXR+XR Interaction Toolkit如何自定义VR按键

    上一篇文章我们介绍了Unity的新版本InputSyste如何使用,这一篇文章,我们主要说一下,在新版基于OpenXR的VR项目中,如何自定义VR按钮的功能。 我们使用XR Interaction Toolkit插件时,它的几个Samples是非常有用的。如下所示: 它们分别是: 1.Starter Assets:官方示例Demo 2.XR Device Simul

    2024年02月15日
    浏览(36)
  • Unity之OpenXR+XR Interaction Toolkit接入Pico VR一体机

    Pico VR 一体机是目前国内比较流行的VR设备之一,PICO成立于2015年3月,于2021年9月并入字节跳动。最新推出的Pico4一体机售价只有2400左右,这让很多家庭都入手了Pico设备,VR一体机的功能包括:VR全景视频,VR运动,VR游戏等等。我们今天就来通过Unity最新的OpenXR标准来接入Pico

    2024年02月04日
    浏览(50)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包