草庐IT

Unity XR实现交互(抓取,移动旋转,传送,射击)-Pico

窗外听轩雨 2023-04-20 原文

Unity XR实现交互(抓取,移动旋转,传送,射击)

文章目录

前言

Unity XR提供了XR Interaction Toolkit交互工具包直接在Package Manager中安装/更新即可,对于简单的交互需求可以实现0代码,只需要将相应的脚本挂载到手柄和物体身上即可。本次演示使用当前最新的2.1.0 preview版本,如果版本较低可能会有部分脚本不可用,请尽可能更新到最新的版本。

本次演示使用Pico XR SDK,在导入SDK后其会自行携带一个XR Interaction Toolkit的0.9版本,请一定从Package Manager中进行更新,否则后续的选项会有较大的区别。

PS: 更新到新版后,很多脚本都提供了新版Action-based方式,和老版Device-based,本篇博客会以Device-based进行讲解,关于Unity新版输入系统的使用,笔者会在下一篇文章着重去讲。

一、手柄的创建

  • Ray Interactor:会创建一个带有射线的手柄模板对象
  • Direct Interactor:会创建一个不具有射线的手柄模板对象
  • XR Origin(VR): 建议,会直接创建出VR摄像机+两个射线手柄对象,更为方便后续可直接在此基础上做更改。

二、手柄的抓取

1. XR DirectController 手柄直接抓取

  • Interaction Manager: 交互管理类 — 关键,一般会随着XR Origin一起创建出来,一般创建手柄会直接挂载上去,如果没有挂载需要去Hireachy面板手动挂载一下。
  • Interaction Layer Mask : 在可抓取物体身上的XR Grab Interactable脚本上也有同名属性,只有物体的Layer Mask和手柄的匹配才可被抓取。
  • Attack Transform : 手柄的抓取位置,同时物体也可以设置抓取位置,当抓取时手柄的抓取位置会和物体的抓取位置相同,根据具体需求加以配置合适的位置即可。
  • 碰撞体:如果不是使用模板配置,而是自行挂载脚本很容易忘记此组件,直接抓取必须具有碰撞体才可以检测到可抓取物体并进行抓取操作,而射线则无需碰撞体,只需射线检测。

2. XR Ray Interactor 手柄射线抓取

手柄射线抓取一般使用默认设置即可实现将击中的物体吸到手柄上,无需添加碰撞体,诸如Layer Mask等属性与上述一致,不再赘述。

3. XR Grab Interactable 可抓取物体

  • Interaction Manager/LayerMask/Attack Transform,几个常用属性在XR DirectController中描述过,不再赘述
  • Collider:必须拥有,抓取是通过碰撞器检测所实现的
  • Rigibody:建议拥有,VR场景下的可抓取物体的抓取投掷等效果均基于自带的刚体。
  • Interactable Events:里面提供了抓取物体一系列事件的回调,如抓取物体的回调,释放物体的回调,抓取物体后按下Trigger键的回调等等,后续的射击功能正是基于此实现的。

三、手柄摇杆控制移动和旋转

以左手摇杆控制持续旋转,右手摇杆控制持续移动为例

根据上图,在XR Origin上添加Locomotion System,Continous Turn Provider等组件,再按照上图箭头进行配置即可。

  • 注意这些脚本不是必须放在XR Origin身上,任意地方均可但属性必须进行配置,放在XR Origin上方便管理。
  • Continous 是持续进行移动和旋转的脚本,由手柄的摇杆控制,如果想一次旋转或移动一段距离/角度,可以用Snap Turn/Move,在低版本的XR互动包中可能会不支持某些脚本。

四、手柄射线传送

1. 基本功能版



  • 基本的传送管理类Teleportion Provider必须要添加,推荐一起添加在XR Origin中

  • 负责传送的手柄,首先必须是XR Ray Interactor射线控制,一般来讲会使用抛物线,或者贝塞尔曲线,关于其相关参数可以搜索贝塞尔曲线的知识,Sample Frequency取样点会直接影响曲线的平滑程度。

  • Reticle为射线击中目标后的指示器,很适合作为传送目标点的指示器,如果没有合适的指示器可以用球体简单演示。

除了射线手柄的设置,在需要传送的地面上还需要添加Teleportation Area脚本(如果想只能传送到固定的点可以用Anchor,用法一致),然后射线检测到可以传送的地面后射线会变为绿色,默认按下Trigger键即可实现传送。

2. 进阶版

待改进的问题

  1. 只挂载默认的脚本,有时很大程度上没法满足需求,例如一般手柄的传送功能不会一直存在曲线去选择位置,我们会希望其在按下某个按键或者推动摇杆时出现曲线旋转位置,在松开按键或摇杆时进行传送等。

  2. 负责传送的手柄无法同时挂载Ray Interactor和Direct Interactor也就是说,我们无法通过仅仅挂载脚本去实现手柄平常负责直接抓取,而想传送时得到射线选取位置传送。

针对问题1,2的场景,笔者以左手柄平常负责直接抓取,按下A键出现射线选择位置传送为例,给出一种解决方案。

基本思路

  1. 创建两个左手柄对象,一个挂载Direct Interactor负责日常抓取,一个挂载Ray Interactor负责传送。
  2. 平常Ray Interactor脚本会被禁用掉,只有当按下A键后启用可以选择位置,当松开A键后代码控制发送传送请求,再禁用掉脚本指示器等等。

关于手柄按键的按下和抬起 Down和Up事件,如果使用老的输入系统可以参考这篇文章https://blog.csdn.net/Q540670228/article/details/123139150,关于脚本的启动禁用过程较为简单,下面只给出抬起按键时发起传送请求的代码。

    //传送管理器脚本的获取省略
	public TeleportationProvider provider;
	//负责传送的手柄XRRayInteractor脚本,获取过程省略
	public XRRayInteractor teleportRayInteractor;
	private void LeftAXButtonUpHandler()
    {
        //射线信息
        RaycastHit rayInfo;
        //判断目标点是否有效 1.是否击中目标 2.是否具有Teleportation组件
        bool isValid = teleportRayInteractor.TryGetCurrent3DRaycastHit(out rayInfo);
        isValid = isValid && rayInfo.collider != null &&
                  (rayInfo.collider.GetComponent<TeleportationArea>() != null ||
                   rayInfo.collider.GetComponent<TeleportationAnchor>() != null);
        if (isValid)
        {
            //创建传送需求将射线击中的位置作为目的地,提交到provider中的传送队列。
            TeleportRequest request = new TeleportRequest();
            request.destinationPosition = rayInfo.point;
            provider.QueueTeleportRequest(request);
        }
        
        //禁用相关脚本和指示器
        teleportRayInteractor.enabled = false;
        teleportRayInteractor.GetComponent<XRInteractorLineVisual>().reticle?.SetActive(false);
    }

五、手柄控制射击

在VR游戏中经常会有捡起枪进行射击的功能,其一般设计难点在

  1. 判断物体是否被抓取,被哪个手柄抓取
  2. 抓取了此物体的手柄是否按下了Trigger键

在XR Grab Interactable脚本中已经很贴心的提供了一个事件,触发条件正是上述这两个。使用方式如下

private XRGrabInteractable grab;
private void Awake()
{
    grab = GetComponent<XRGrabInteractable>();
    //为activated事件添加监听函数即可
    grab.activated.AddListener(GrabHandler);
}

private void GrabHandler(ActivateEventArgs a)
{
	//当枪械被抓取和按下Trigger后回调此方法,触发射击方法。
    Shoot();
}

有关Unity XR实现交互(抓取,移动旋转,传送,射击)-Pico的更多相关文章

  1. ruby - 多次弹出/移动 ruby​​ 数组 - 2

    我的代码目前看起来像这样numbers=[1,2,3,4,5]defpop_threepop=[]3.times{pop有没有办法在一行中完成pop_three方法中的内容?我基本上想做类似numbers.slice(0,3)的事情,但要删除切片中的数组项。嗯...嗯,我想我刚刚意识到我可以试试slice! 最佳答案 是numbers.pop(3)或者numbers.shift(3)如果你想要另一边。 关于ruby-多次弹出/移动ruby​​数组,我们在StackOverflow上找到一

  2. ruby-on-rails - 如何在 ruby​​ 交互式 shell 中有多行? - 2

    这可能是个愚蠢的问题。但是,我是一个新手......你怎么能在交互式ruby​​shell中有多行代码?好像你只能有一条长线。按回车键运行代码。无论如何我可以在不运行代码的情况下跳到下一行吗?再次抱歉,如果这是一个愚蠢的问题。谢谢。 最佳答案 这是一个例子:2.1.2:053>a=1=>12.1.2:054>b=2=>22.1.2:055>a+b=>32.1.2:056>ifa>b#Thecode‘if..."startsthedefinitionoftheconditionalstatement.2.1.2:057?>puts"f

  3. ruby - 如何根据特征实现 FactoryGirl 的条件行为 - 2

    我有一个用户工厂。我希望默认情况下确认用户。但是鉴于unconfirmed特征,我不希望它们被确认。虽然我有一个基于实现细节而不是抽象的工作实现,但我想知道如何正确地做到这一点。factory:userdoafter(:create)do|user,evaluator|#unwantedimplementationdetailshereunlessFactoryGirl.factories[:user].defined_traits.map(&:name).include?(:unconfirmed)user.confirm!endendtrait:unconfirmeddoenden

  4. ruby-on-rails - 如何重命名或移动 Rails 的 README_FOR_APP - 2

    当我在我的Rails应用程序根目录中运行rakedoc:app时,API文档是使用/doc/README_FOR_APP作为主页生成的。我想向该文件添加.rdoc扩展名,以便它在GitHub上正确呈现。更好的是,我想将它移动到应用程序根目录(/README.rdoc)。有没有办法通过修改包含的rake/rdoctask任务在我的Rakefile中执行此操作?是否有某个地方可以查找可以修改的主页文件的名称?还是我必须编写一个新的Rake任务?额外的问题:Rails应用程序的两个单独文件/README和/doc/README_FOR_APP背后的逻辑是什么?为什么不只有一个?

  5. 旋转矩阵的几何意义 - 2

    点向量坐标矩阵的几何意义介绍旋转矩阵的几何含义之前,先介绍一下点向量坐标矩阵的几何含义点:在一维空间下就是一个标量,如同一条直线上,以任意某一个位置为0点,以一定的尺度间隔为1,2,3...,相反方向为-1,-2,-3...;如此就形成了一维坐标系,这时候任何一个点都可以用一个数值表示,如点p1=5,即即从原点出发沿着x轴正方向移动5个尺度;点p2=-3,负方向移动3个尺度;     在一维坐标系上过原点做垂直于一维坐标系的直线,则形成了二维坐标系,此时描述一个点需要两个数值来表示点p3=(3,2),即从原点出发沿着x轴正方向移动3个尺度,在此基础上沿着y轴正方向移动两个尺度的位置就是点p3。

  6. 华为OD机试用Python实现 -【明明的随机数】 2023Q1A - 2

    华为OD机试题本篇题目:明明的随机数题目输入描述输出描述:示例1输入输出说明代码编写思路最近更新的博客华为od2023|什么是华为od,od薪资待遇,od机试题清单华为OD机试真题大全,用Python解华为机试题|机试宝典【华为OD机试】全流程解析+经验分享,题型分享,防作弊指南华为o

  7. Unity 3D 制作开关门动画,旋转门制作,推拉门制作,门把手动画制作 - 2

    Unity自动旋转动画1.开门需要门把手先动,门再动2.关门需要门先动,门把手再动3.中途播放过程中不可以再次进行操作觉得太复杂?查看我的文章开关门简易进阶版效果:如果这个门可以直接打开的话,就不需要放置"门把手"如果门把手还有钥匙需要旋转,那就可以把钥匙放在门把手的"门把手",理论上是可以无限套娃的可调整参数有:角度,反向,轴向,速度运行时点击Test进行测试自己写的代码比较垃圾,命名与结构比较拉,高手轻点喷,新手有类似的需求可以拿去做参考上代码usingSystem.Collections;usingSystem.Collections.Generic;usingUnityEngine;u

  8. 基于C#实现简易绘图工具【100010177】 - 2

    C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.

  9. ruby-on-rails - rbenv:从 RVM 移动到 rbenv 后,在 Jenkins 执行 shell 中找不到命令 - 2

    我从Ubuntu服务器上的RVM转移到rbenv。当我使用RVM时,使用bundle没有问题。转移到rbenv后,我在Jenkins的执行shell中收到“找不到命令”错误。我内爆并删除了RVM,并从~/.bashrc'中删除了所有与RVM相关的行。使用后我仍然收到此错误:rvmimploderm~/.rvm-rfrm~/.rvmrcgeminstallbundlerecho'exportPATH="$HOME/.rbenv/bin:$PATH"'>>~/.bashrcecho'eval"$(rbenvinit-)"'>>~/.bashrc.~/.bashrcrbenvversions

  10. MIMO-OFDM无线通信技术及MATLAB实现(1)无线信道:传播和衰落 - 2

     MIMO技术的优缺点优点通过下面三个增益来总体概括:阵列增益。阵列增益是指由于接收机通过对接收信号的相干合并而活得的平均SNR的提高。在发射机不知道信道信息的情况下,MIMO系统可以获得的阵列增益与接收天线数成正比复用增益。在采用空间复用方案的MIMO系统中,可以获得复用增益,即信道容量成倍增加。信道容量的增加与min(Nt,Nr)成正比分集增益。在采用空间分集方案的MIMO系统中,可以获得分集增益,即可靠性性能的改善。分集增益用独立衰落支路数来描述,即分集指数。在使用了空时编码的MIMO系统中,由于接收天线或发射天线之间的间距较远,可认为它们各自的大尺度衰落是相互独立的,因此分布式MIMO

随机推荐