十、pico+Unity交互开发教程——射线抓取与更多交互功能

一、回顾与引入

复制代码
回顾上一篇直接抓取的教程,VR交互一般需要可交互的对象(Interactable)和发起交互的对象(Interactor)。直接抓取和射线抓取的可交互对象无区别,可参考上一篇教程设置组件。

两者区别在于发起交互的对象不同,直接抓取使用XR Direct Interactor,而射线抓取使用XR Ray Interactor,它可通过射线检测实现远距离交互。

二、添加射线功能的相关组件

  1. XR Origin下的LeftHand ControllerRightHand Controller物体创建子物体,选择XR -> Ray Interactor(Action-based),并命名为Distance Grab Interactor

  2. 删除子物体上的XR Controller,设置LeftHandRightHandTag以实现左右手切换抓取。

  3. 设置XR Ray Interactor上的射线发射起始点Ray Origin TransformXR Interactor Line Visual的颜色效果,可参考射线交互教程。

  4. DistanceGrabInteractor物体拖到Left/RightHand Controller上的XR Interaction Group中,确保一个Interactor被使用时其他Interactor暂时失效。

四、设置Interaction Layer Mask 层级,上一篇说过

  1. 运行程序时发现射线射到地面会激活传送,这是因为XR Ray Interactor的Interaction Layer Mask默认是Everything,而地面的Interaction Layer Mask是Teleport,可交互物体默认是Default。将XR Ray Interactor的Interaction Layer Mask改为Default可解决此问题。

  2. 也可分别为直接抓取和射线抓取设立不同的Interaction Layer,以区分可被不同方式抓取的物体。

五、防止射线抓取的射线与UI发生交互

  1. 当通过射线抓取物体后朝向UI,会发现手部发出射线并能与UI交互,这是DistanceGrab Interactor发出的射线。
  2. 找到DistancegGrab Interactor物体上的XR Ray Interactor组件,取消勾选Raycast Mask的UI选项,防止远距离抓取的射线与UI发生响应。

六、让XR Direct Interactor不对XR Ray Interactor产生干扰(新版XRI不会出现此问题)

  1. 注:此部分针对XR Interaction Toolkit 2.1.1版本,若使用2.3.2或更高版本可跳过。

  2. 当用射线抓取物体后,可能会出现即使按住手柄Grip键不放,也会不小心将另一个物体"吸"过来的问题,这是XR Direct Interactor对XR Ray Interactor产生干扰。

  3. 解决思路是写一个脚本控制,当XR Direct Interactor发挥作用时,将XR Ray Interactor隐藏掉。

  4. 创建脚本GrabRayController,在LeftHand Controller和Right Controller物体上挂载并赋值变量,可解决此问题。

csharp 复制代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.XR.Interaction.Toolkit;

// 抓取射线控制器类
public class GrabRayController : MonoBehaviour
{
    // 射线交互器
    public XRRayInteractor grabRayInteractor;
    // 直接交互器
    public XRDirectInteractor grabDirectInteractor;

    void Update()
    {
        // 根据直接交互器选中的可交互对象数量来决定射线交互器是否启用。
        // 如果直接交互器没有选中任何可交互对象(即数量为0),则启用射线交互器;否则禁用射线交互器。
        grabRayInteractor.enabled = grabDirectInteractor.interactablesSelected.Count == 0;
    }
}

七、使抓取的物体不会吸到手上(Force Grab)

  1. 若想在抓取时让物体和手保持一定距离,营造远程操纵物体的感觉,可取消XR Ray Interactor脚本中的Force Grab勾选。

  2. 若想让射线射到物体上的点作为实际抓取点,可勾选Dynamic Attach。

八、远距离抓取时通过摇杆改变抓取物体的位移和旋转角度(Rotate Anchor Action和Translate Anchor Action)

  1. 在测试射线抓取场景时,发现取消Force Grab后,按下手柄Grip键抓取物体再推动摇杆,物体会发生位移和旋转角度变化,这是由XR Controller(Action-based)和XR Ray Interactor组件的设置引起。
  2. XR Controller(Action-based)上的Rotate Anchor Action和Translate Anchor Action引用了Input System中的Action,可通过查看默认输入配置文件进行设置调整。
  3. XR Ray Interactor上的Anchor Control也与此功能相关。
  4. 当然,如果你不想要远距离抓取时通过摇杆改变抓取物体的位移和旋转角度的功能,就直接将左右手 XR Controller 中的 Rotate Anchor Action 和 Translate Anchor Action 的 Use Reference 取消勾选,然后移除下面新建的 Grab Ray Controller 脚本就行了。

但是可以发现,触发 Rotate Anchor 或 Translate Anchor 的时候也会触发其他与摇杆控制有关的动作,比如传送,持续移动。因此我们希望在对远距离抓取物体进行操作时,不会触发该手柄其他和摇杆控制绑定的动作。

csharp 复制代码
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.XR.Interaction.Toolkit;

// 抓取射线控制器类
public class GrabRayController : MonoBehaviour
{
    // 射线交互器
    public XRRayInteractor grabRayInteractor;
    // 直接交互器
    public XRDirectInteractor grabDirectInteractor;

    // 旋转锚点动作引用
    public InputActionReference rotateAnchorReference;
    // 平移锚点动作引用
    public InputActionReference translateAnchorReference;
    // 传送激活动作引用
    public InputActionReference teleportActivateReference;
    // 移动动作引用
    public InputActionReference moveReference;
    // 转向动作引用
    public InputActionReference turnReference;

    private void Start()
    {
        // 为射线交互器的 selectEntered 事件添加监听器,当抓取开始时调用 OnEnterGrab 方法
        grabRayInteractor.selectEntered.AddListener(OnEnterGrab);
        // 为射线交互器的 selectExited 事件添加监听器,当抓取结束时调用 OnExitGrab 方法
        grabRayInteractor.selectExited.AddListener(OnExitGrab);
    }

    private void OnDestroy()
    {
        // 在对象销毁时,移除 selectEntered 事件的监听器
        grabRayInteractor.selectEntered.RemoveListener(OnEnterGrab);
        // 在对象销毁时,移除 selectExited 事件的监听器
        grabRayInteractor.selectExited.RemoveListener(OnExitGrab);
    }

    private void OnEnterGrab(SelectEnterEventArgs arg)
    {
        // 禁用传送激活动作
        DisableAction(teleportActivateReference);
        // 禁用移动动作
        DisableAction(moveReference);
        // 禁用转向动作
        DisableAction(turnReference);
        // 启用旋转锚点动作
        EnableAction(rotateAnchorReference);
        // 启用平移锚点动作
        EnableAction(translateAnchorReference);
    }

    private void OnExitGrab(SelectExitEventArgs arg)
    {
        // 启用传送激活动作
        EnableAction(teleportActivateReference);
        // 启用移动动作
        EnableAction(moveReference);
        // 启用转向动作
        EnableAction(turnReference);
        // 禁用旋转锚点动作
        DisableAction(rotateAnchorReference);
        // 禁用平移锚点动作
        DisableAction(translateAnchorReference);
    }

    private void EnableAction(InputActionReference actionReference)
    {
        // 根据动作引用获取输入动作
        var action = GetInputAction(actionReference);
        // 如果动作不为空且未启用,则启用该动作
        if (action!= null &&!action.enabled)
            action.Enable();
    }

    private void DisableAction(InputActionReference actionReference)
    {
        // 根据动作引用获取输入动作
        var action = GetInputAction(actionReference);
        // 如果动作不为空且已启用,则禁用该动作
        if (action!= null && action.enabled)
            action.Disable();
    }

    private InputAction GetInputAction(InputActionReference actionReference)
    {
        // 如果动作引用不为空,则返回对应的输入动作,否则返回 null
        return actionReference!= null? actionReference.action : null;
    }
}

然后在 LeftHand Controller 和 RightHand Controller 物体上分别挂载这个脚本,并且手动赋值。

通过以上步骤,我们实现了Unity VR中的射线抓取功能以及更多复杂的交互控制,为VR体验增添了丰富性和真实感。

相关推荐
AA陈超11 小时前
虚幻引擎5 GAS开发俯视角RPG游戏 P06-19 打开属性菜单
c++·游戏·ue5·游戏引擎·虚幻
向宇it11 小时前
【推荐100个unity插件】unity易于使用模块化设计的天空、体积云和天气系统——Enviro 3
游戏·3d·unity·c#·游戏引擎
怣疯knight1 天前
unity实现2D人物从上面踩踏敌人,敌人减血的简易方法(类似马里奥的攻击手段)
unity·游戏引擎
这张生成的图像能检测吗1 天前
(论文速读)InteractVLM: 基于2D基础模型的3D交互推理
人工智能·计算机视觉·交互·生成模型·图像生成·视觉语言模型·3d重建
AA陈超1 天前
虚幻引擎5 GAS开发俯视角RPG游戏 P06-16 属性菜单 - 构建
c++·游戏·ue5·游戏引擎·虚幻
周杰伦_Jay2 天前
【常用设计模式全解析】创建型模式(聚焦对象创建机制)、结构型模式(优化类与对象的组合关系)、行为型模式(规范对象间的交互行为)
设计模式·架构·开源·交互·1024程序员节
井队Tell2 天前
打造高清3D虚拟世界|零基础学习Unity HDRP高清渲染管线(第五天)
学习·3d·unity
yi碗汤园2 天前
【一文了解】八大排序-插入排序、希尔排序
开发语言·算法·unity·c#·1024程序员节
MoonBit月兔2 天前
MoonBit Pearls Vol.12:初探 MoonBit 中的 JavaScript 交互
开发语言·javascript·数据库·交互·moonbit
AA陈超3 天前
虚幻引擎5 GAS开发俯视角RPG游戏 P06-14 属性菜单 - 文本值行
c++·游戏·ue5·游戏引擎·虚幻