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

文章目录

  • 教程说明
  • VR 交互的类型
  • 发起交互的对象(Interactor)
    • ⭐XR Direct Interactor 脚本
    • ⭐添加可交互区域
  • 可交互的对象(Interactable)
    • ⭐添加刚体
    • ⭐XR Simple Interactable 脚本
    • ⭐Interactable Events
    • ⭐XR Grab Interactable 脚本
      • ⚡三种 Movement Type
      • ⚡Attach Transform 抓取点
      • ⚡代码实现 Use 功能(制作简易手枪)
        • 核心脚本
        • 制作子弹(碰撞检测方式设为 Continous Dynamic)
        • 制作子弹发射位置
        • 优化一:左右手抓取(判断哪只手与物体交互)
        • 优化二:防止传送射线误触发远距离抓取(Interaction Layer Mask)
      • ⚡其他功能一:将与物体接触的地方作为抓取点(Dynamic Attach)
    • ⭐XR Tint Interactable Visual 脚本

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

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


教程说明

使用的 Unity 版本: 2020.3.36

使用的 VR 头显: Oculus Quest 2

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

项目源码(持续更新):https://github.com/YY-nb/Unity_XRInteractionToolkit_Tutorial2022/tree/master

最终实现的效果:

Unity VR开发教程 OpenXR+XR Interaction Toolkit 2.1.1 (六)手与物品交互(触摸、抓取)_第1张图片


VR 交互的类型

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

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

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


发起交互的对象(Interactor)

⭐XR Direct Interactor 脚本

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

Unity VR开发教程 OpenXR+XR Interaction Toolkit 2.1.1 (六)手与物品交互(触摸、抓取)_第2张图片

其中,LeftHand Controller 和 RightHand Controller 是专门负责手部的交互的,因此我们只需在这两个游戏物体上去添加组件或脚本。

为了让双手成为发起交互的对象,我们需要在这两个游戏物体上添加 XR Direct Interactor 脚本。

Unity VR开发教程 OpenXR+XR Interaction Toolkit 2.1.1 (六)手与物品交互(触摸、抓取)_第3张图片

⭐添加可交互区域

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

Unity VR开发教程 OpenXR+XR Interaction Toolkit 2.1.1 (六)手与物品交互(触摸、抓取)_第4张图片


可交互的对象(Interactable)

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

Unity VR开发教程 OpenXR+XR Interaction Toolkit 2.1.1 (六)手与物品交互(触摸、抓取)_第5张图片

在这里插入图片描述

⭐添加刚体

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

⭐XR Simple Interactable 脚本

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

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

Unity VR开发教程 OpenXR+XR Interaction Toolkit 2.1.1 (六)手与物品交互(触摸、抓取)_第6张图片

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

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

Unity VR开发教程 OpenXR+XR Interaction Toolkit 2.1.1 (六)手与物品交互(触摸、抓取)_第7张图片

⭐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 2.1.1 (六)手与物品交互(触摸、抓取)_第8张图片

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

Unity VR开发教程 OpenXR+XR Interaction Toolkit 2.1.1 (六)手与物品交互(触摸、抓取)_第9张图片

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

Unity VR开发教程 OpenXR+XR Interaction Toolkit 2.1.1 (六)手与物品交互(触摸、抓取)_第10张图片

可以看到 XRI LeftHand Interaction 或者 XRI RightHand Interaction 下就有 Select 和 Activate。Select 动作绑定的是 “按下 Grip 键” 这个操作,Activate 动作绑定的是 “按下 Trigger 键” 这个操作。

Unity VR开发教程 OpenXR+XR Interaction Toolkit 2.1.1 (六)手与物品交互(触摸、抓取)_第11张图片

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

Unity VR开发教程 OpenXR+XR Interaction Toolkit 2.1.1 (六)手与物品交互(触摸、抓取)_第12张图片

这时候,也许有人会有疑问:在上一篇 UI Demo 中,我们也有用到 Activate 这个动作,作用是按下 Trigger 键与 UI 进行交互。虽然 XR Controller 中是 Select Action 绑定的是 Select 这个动作,但是当 UI 射线射到 UI 上时,射线的颜色变成了白色,说明此时已经进入了选中的状态,而我们无需按下 Grip 键才能进入选中状态。

Unity VR开发教程 OpenXR+XR Interaction Toolkit 2.1.1 (六)手与物品交互(触摸、抓取)_第13张图片

这是因为 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 2.1.1 (六)手与物品交互(触摸、抓取)_第14张图片

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

⚡三种 Movement Type

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

Unity VR开发教程 OpenXR+XR Interaction Toolkit 2.1.1 (六)手与物品交互(触摸、抓取)_第15张图片

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

Unity VR开发教程 OpenXR+XR Interaction Toolkit 2.1.1 (六)手与物品交互(触摸、抓取)_第16张图片
Unity VR开发教程 OpenXR+XR Interaction Toolkit 2.1.1 (六)手与物品交互(触摸、抓取)_第17张图片

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

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

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

⚡Attach Transform 抓取点

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

Unity VR开发教程 OpenXR+XR Interaction Toolkit 2.1.1 (六)手与物品交互(触摸、抓取)_第18张图片

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

Unity VR开发教程 OpenXR+XR Interaction Toolkit 2.1.1 (六)手与物品交互(触摸、抓取)_第19张图片

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

Unity VR开发教程 OpenXR+XR Interaction Toolkit 2.1.1 (六)手与物品交互(触摸、抓取)_第20张图片

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

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

Unity VR开发教程 OpenXR+XR Interaction Toolkit 2.1.1 (六)手与物品交互(触摸、抓取)_第22张图片

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

Unity VR开发教程 OpenXR+XR Interaction Toolkit 2.1.1 (六)手与物品交互(触摸、抓取)_第23张图片
Unity VR开发教程 OpenXR+XR Interaction Toolkit 2.1.1 (六)手与物品交互(触摸、抓取)_第24张图片
Unity VR开发教程 OpenXR+XR Interaction Toolkit 2.1.1 (六)手与物品交互(触摸、抓取)_第25张图片

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

值得注意的是,仅设置 Attach Transform 只是粗略地抓取。因为它在物理效果上显得不是很真实,可以看到物体和手之间还是有穿模的现象。如果要实现精细地抓取,会稍微麻烦一点,今后也会出相应的教程进行详细说明。

关于 XR Grab Interactable 脚本的其他变量设置,大家可以参考官方文档:
https://docs.unity3d.com/Packages/[email protected]/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 2.1.1 (六)手与物品交互(触摸、抓取)_第26张图片
这里有个小坑需要注意一下,就是我们最好要把子弹 Rigidbody 的 Collision Detection 设为 Continous Dynamic,否则因为子弹是高速运动的,有时候会检测不到和刚体的碰撞,造成子弹直接从物体中间穿过去。

Unity VR开发教程 OpenXR+XR Interaction Toolkit 2.1.1 (六)手与物品交互(触摸、抓取)_第27张图片

制作子弹发射位置

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

Unity VR开发教程 OpenXR+XR Interaction Toolkit 2.1.1 (六)手与物品交互(触摸、抓取)_第28张图片

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

Unity VR开发教程 OpenXR+XR Interaction Toolkit 2.1.1 (六)手与物品交互(触摸、抓取)_第30张图片

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

大功告成!

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

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

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

Unity VR开发教程 OpenXR+XR Interaction Toolkit 2.1.1 (六)手与物品交互(触摸、抓取)_第31张图片

然后,我们需要修改之前写的 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,所以不要忘了在编辑器中进行赋值,并且给 LeftHand Controller 和 RightHand Controller 加上 Tag 哦。

Unity VR开发教程 OpenXR+XR Interaction Toolkit 2.1.1 (六)手与物品交互(触摸、抓取)_第32张图片
在这里插入图片描述
在这里插入图片描述

最终效果:

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

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

Unity VR开发教程 OpenXR+XR Interaction Toolkit 2.1.1 (六)手与物品交互(触摸、抓取)_第33张图片

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

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

Unity VR开发教程 OpenXR+XR Interaction Toolkit 2.1.1 (六)手与物品交互(触摸、抓取)_第34张图片
Unity VR开发教程 OpenXR+XR Interaction Toolkit 2.1.1 (六)手与物品交互(触摸、抓取)_第35张图片

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

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

Unity VR开发教程 OpenXR+XR Interaction Toolkit 2.1.1 (六)手与物品交互(触摸、抓取)_第36张图片
因为 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 2.1.1 (六)手与物品交互(触摸、抓取)_第37张图片

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

Unity VR开发教程 OpenXR+XR Interaction Toolkit 2.1.1 (六)手与物品交互(触摸、抓取)_第38张图片
Unity VR开发教程 OpenXR+XR Interaction Toolkit 2.1.1 (六)手与物品交互(触摸、抓取)_第39张图片
然后把 XR Direct Interactor 的 Interaction Layer Mask 改为 Default,这样用于抓取的 Interactor 和 Interactable 的层级是相同的,不会对其他的交互方式产生干扰。当然,我们也可以为抓取单独设立一个 Interaction Layer Mask。重要的是搞清楚 Interaction Layer Mask 的作用。

Unity VR开发教程 OpenXR+XR Interaction Toolkit 2.1.1 (六)手与物品交互(触摸、抓取)_第40张图片

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

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

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

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

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

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

Unity VR开发教程 OpenXR+XR Interaction Toolkit 2.1.1 (六)手与物品交互(触摸、抓取)_第42张图片

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

效果:


⭐XR Tint Interactable Visual 脚本

Unity VR开发教程 OpenXR+XR Interaction Toolkit 2.1.1 (六)手与物品交互(触摸、抓取)_第43张图片

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

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


你可能感兴趣的:(Unity,VR,vr,unity,xr)