文章目录

  • 前言
  • 一、准备工作
    • 1.引入插件
    • 2.准备模型
  • 二、需求拆解
  • 三、实现部分
    • 1.纸飞机抓握,扔出
    • 2.抛物线
    • 3.特效
    • 4.手柄力反馈
  • 总结

前言

在oculus quest2里的first step应用里体验了多种有趣的交互,如乒乓球,遥控飞艇,拉线火箭,纸飞机等。其中尤以纸飞机给我的手感最为特殊(VR纸飞机哪里来的手感啊喂,还不是有需求就做喽)。这里就大概记录一下其间的开发历程。


一、准备工作

1.引入插件

steamvr plugin2.x的版本对输入都做了单独的隔离,可以很方便地适应多种输入设备和多重输入模式的开发。同时,其中提供的基础脚本组件也十分完备且可理解(Hand,Throwable,Laser等等),在它基础上可以很快进行开发且拓展性良好。但是相对的steamvr plugin不兼容VRTK(VR tool kit,不再更行了,时代的眼泪),对习惯了VRTK的人来讲不得不说是一种遗憾。


具体操作:再asset store里搜索steamvr plugin,下载导入,接受所有的弹框,完毕后,找到window -> steamvr input,点击。

保持默认,点击save and generate。

基本的开发环境就布置好了,打开Interaction_Example场景,里面依旧存放了一些制作好的交互物体了。

2.准备模型

拖入一个cube作为放置纸飞机的台子。

随便找一个纸飞机的模型,导入到unity,拖到场景中,并赋予合适材质,如图:


对飞机模型进行简要处理:目的是保持z轴正方向和飞机的朝向一致,做法就是建一个根节点,并将飞机模型拖入作为子节点,并适当调整方向。

OK,到这里准备工作基本完成。下面看看我们到底要干什么,该怎么干。

二、需求拆解

那么扔纸飞机到底是一个怎样的过程呢?你要用自己的虚拟手(左手右手其中一只)“捏”起飞机,然后扔出,飞机通过手的带动获得一个初速度(包含大小和方向),以与手脱离的点为初始点做一个平抛的运动。整体过程基本上就是这样,是不是感觉回到了高中基本物理。

当然,学过大学物理,尤其是流体力学的小伙伴都明白,纸飞机依照构造不同,抛出角度和速度的不同,其轨迹千差万别,千奇百怪(例如,纸飞机在空中的突然急转,原因是因为飞机的结构以及空气流体的影响)。我尝试了去构建纸飞机在空气流体中运动的理论模型,把压强、对流等都考虑了进去,做了很多这方面的研究后发现(其实是模型越搞越混乱,笔者只是大学上过一点力学的小白),其实这陷入到了一个误区:在游戏引擎里去追求真实的力学仿真。花这么大力气去“模拟”现实,不如把精力用在改善用户体验上(“超脱”现实),遂放弃。

用户体验又从两方面可以入手――视觉反馈和力反馈,对应头显和手柄。视觉上,抛物线要尽量柔美,不能太过剧烈,同时需要一些视觉辅助(如拖尾和一些其他特效等)。力反馈的话,主要是体现在手柄的震动上,即要让使用者在抓握到纸飞机时体会到与什么都没抓握到时不一样的感觉。

总结下来,需求部分如下:

  1. 纸飞机抓握,扔出
  2. 纸飞机扔出时轨迹是抛物线
  3. 纸飞机飞行特效
  4. 抓握纸飞机的手柄反馈

三、实现部分

1.纸飞机抓握,扔出

在开发之前,我们先要了解一下Player这个预制体(prefab)。可以理解为它包含了我们的vr camera和两只手并处理其输入响应,负责将这三者映射到虚拟环境中(当然还有一些其他的组件,例如负责输入模式调控的InputModule,debug组件等)。简单来说,将这个场景中有了这个prefab之后,你戴上头显启动应用,就可以进入到虚拟环境中通过头显看到虚拟环境中的物体以及自己的虚拟双手了。

回到我们之前构建好的场景(Interactions_Example)中,此时物体上没有挂任何脚本,所以暂时没有任何交互效果。

为PAP(我们纸飞机的根节点)添加碰撞体组件(我选用了BoxCollider)和Interactable脚本(steamvr plugin里的),并适当调节碰撞体:

此时,启动应用进入虚拟环境,发现手在进入模型碰撞体后,已经可以高亮模型了。

但是这还不够,试着去抓握的话,物体并没有与手的有效互动,此时需要添加另一个脚本组件Throwable(也是steamvr plugin里的)。添加了这一脚本后,会自动为物体添加刚体Rigidbody组件。此时,再次进入虚拟环境,并尝试抓握纸飞机:

纸飞机可以被顺利抓起并且丢出,但是此时也发现,在抓握纸飞机的瞬间,手部模型消失不见。我们详细看一下Interactable脚本组件:

其中bool量 HideHandOnAttach表示在被抓握时隐藏手部模型,取消勾选。

嗯~好像还是不太对,手的姿势奇奇怪怪的,那么就k一个手势上去好了。添加SteamVR_Skeleton_Poser脚本。


点击Create创建对应姿势文件,并找一个合适的文件夹存入。而相应的,编辑器内,模型根节点下,会多出两个手部模型的克隆文件,如图:

所谓k姿势,就是去摆弄下面两个手部模型,“k”到合适的姿势,在触发交互操作时,手部会自动使用对应的姿势。记得k好姿势后,点击“Save Pose”。

好像像那么点样子了,我就不去仔细k它的样子了,这个手势可以随时回来微调,但是一定要记得保存,我们进入虚拟环境看一下:
效果还可以,那么这部分基本就完成了,我们借助了steamvr plugin提供的Interactable和Throwable组件实现了交互,并通过它提供的组件去k了手势。

当然,这两个脚本内涵丰富,光是其提供的功能就可以让我们实现很多不同的效果,你可以自行去调试切换,如切换Throwable里AttachmentFlags里面的内容,和Interactable中AttachEaseIn的开关等。

2.抛物线

因为使用了Rigidbody,即Unity的物理模块,所以扔出去的物体很自然是一个弧线(抛物线)。但是仍然有一些问题待解决:现在扔出去纸飞机就像扔出去一个砖块一样,没有办法保持飞机尖儿冲向运动方向;重力感觉太强,没有体现出空气浮力的感觉。

针对这两点,我们写脚本解决:添加自定义脚本,名称为PAPController,如下

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class PAPController : MonoBehaviour
{        [Range(0,9.81f)]public float buoyancy = 8f;private Hand _hand;private Interactable _interactable;private Transform paperAirplane;private Rigidbody _rigidbody;private ConstantForce _constantForce;// Start is called before the first frame updateprivate void Awake(){paperAirplane = GetComponent<Transform>();_rigidbody = GetComponent<Rigidbody>();_constantForce = GetComponent<ConstantForce>();_interactable = GetComponent<Interactable>();}private void Start(){ //添加浮力_constantForce.force = new Vector3(0, buoyancy, 0); }// Update is called once per framevoid FixedUpdate(){//每帧将方向矫正为速度方向paperAirplane.forward = _rigidbody.velocity.normalized;}
}

添加ConstantForce组件

现在可以试试丢出去的手感啦。

3.特效

这里的特效我们主要做拖尾的特效,借助的是unity自带的TrailRenderer这个组件

可以分别做几个不同的拖尾(基于颜色,持续时间,甚至于shader的不同),

效果:

4.手柄力反馈

力反馈在Hand脚本里,有一个专门的封装好的函数可以使用,即TriggerHapticPulse。
具体简单的调用为:

    private void Update(){if (!_interactable.attachedToHand){return;}if (_hand != _interactable.attachedToHand){_hand = _interactable.attachedToHand;}_hand.TriggerHapticPulse(0);}

参数可以具体调节,同样的参数视硬件不同反馈强度也会有一定的不同。

最后再做一点点修饰(加了状态切换)(从我写的下一个脚本开始我就开始写注释,我发四)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Valve.VR;
using Valve.VR.InteractionSystem;public class PAPController : MonoBehaviour
{[Range(0,9.81f)]public float buoyancy = 8f;private enum PAPStat { InAir,InHand,ShouldbeStatic};private PAPStat stat = PAPStat.ShouldbeStatic;private Hand _hand;private Interactable _interactable;private Transform paperAirplane;private Rigidbody _rigidbody;private ConstantForce _constantForce;private void Awake(){paperAirplane = GetComponent<Transform>();_rigidbody = GetComponent<Rigidbody>();_constantForce = GetComponent<ConstantForce>();_interactable = GetComponent<Interactable>();}private void Start(){ _constantForce.force = new Vector3(0, buoyancy, 0); }void FixedUpdate(){if (stat == PAPStat.InAir ){paperAirplane.forward = _rigidbody.velocity.normalized;}}private void Update(){if (!_interactable.attachedToHand){return;}if (_hand != _interactable.attachedToHand){_hand = _interactable.attachedToHand;}_hand.TriggerHapticPulse(0);}public void ChangeStatToInAir(){if (stat != PAPStat.InAir){stat = PAPStat.InAir;}}public void OnCollisionEnter(Collision collision){if (collision.transform.tag != "Player"){stat = PAPStat.ShouldbeStatic;}}
}

总结

本文展示了笔者从灵感思路,到编程实现的全过程,功能和代码结构当然还是有待完善和优化的地方,但是这种面对问题和解决问题的方式我认为还是有可取之处的。

对于我自身来说,写文章的目的既是希望能够对自己做的东西有个清晰的认识,同时也希望能够将这些微不足道的经验进行总结分享,帮助到更多跟我处于同一阶段的人。

VR之 扔一个纸飞机吧相关推荐

  1. tarball_如何在墙上扔一个tarball

    tarball 开源一个成熟的商业软件需要花费很多钱,即使您所做的只是"在墙上扔一个压缩包". 这就是为什么放弃不再关心的软件的公司很少将其开源,而那些放弃开源项目的公司则很少将它 ...

  2. 如何用 Python 画一个纸飞机?| 原力计划

    [CSDN编者按]如果你是一个80后,可能对于卓依婷的歌曲<纸飞机>并不陌生.歌词里说:"飞在风里的纸飞机,载满我对你的情和意.飞到那思念的另一边,诉说我心中的痴迷." ...

  3. 通过扔一个诱饵进行无源无监督域适应

    摘要 无监督域适应(UDA)旨在转移一个标签源域中学到的信息到一个无标记的目标域.现有的UDA方法要求适应中接触源数据,在实际应用中可能不可行.本文中,我们解决了无源无监督域适应问题(SFUDA),其 ...

  4. pythonturtle画飞机_如何用 Python 画一个纸飞机?| 原力计划

    以下文章来源于一粒微小的尘埃 ,作者一粒微小的尘埃 [CSDN 编者按]如果你是一个 80 后,可能对于卓依婷的歌曲<纸飞机>并不陌生.歌词里说:" 飞在风里的纸飞机,载满我对你 ...

  5. unity vr是加一个摄像机就行吗_Unity实时光线追踪功能演示项目创作过程

    今年3月,Unity宣布提供针对NVIDIA RTX实时光线追踪技术的支持,实时光线追踪技术为Unity的高清晰渲染管线HDRP加入了逼真的光照质量,给Unity的视觉功能赋予新的潜力. Unity中 ...

  6. unity vr是加一个摄像机就行吗_《狮子王》:引入VR虚拟制作技术的真人动画电影...

    迪士尼动画电影<狮子王>自2019年7月12日上映以来,排场几近爆满,深受影迷喜爱,目前三天多的票房总计已高达四亿.其实从去年11月23日爆出预告片以后,迪士尼动画粉的胃口就已经被吊了起来 ...

  7. 我们梳理了一下VR教育,感觉它将会是下一个蓝海

    VR垂直行业应用"包罗万象",VR教育是其中关键的一环,一文带你看懂VR教育产业链的发展. 2014年,当Oculus被小扎收购,大家震惊于VR有什么魅力,会被Facebook如此 ...

  8. 有五只猴子分一堆桃子.第一只猴子最先来,扔了一个后平分成五分,拿走了一份.其他猴子也一样扔了一个,平分成5分,拿走自己的.问:桃子至少有几个?

    自己也特意看了很多有关该题的解题过程,无非由是以下特点: 1.从1挨个遍历 2.递归 3.没有解题思路 因此,从解法上做了一些优化,补充了解题思路,剔除递归,如有更好的解题方法可以留言方便一起学习. ...

  9. 如何使用aframe.js构建一个简单的VR播放器

    在当今这个信息化的时代,虚拟现实(VR)已经开始逐渐成为一种新的生活方式.作为一名前端开发工程师,在学习和探索VR技术方面,aframe.js是一个非常有趣和有用的工具.在本文中,我将介绍如何使用af ...

最新文章

  1. SQLite 源码仓库(Repository)
  2. SQL关闭自增长列标识:SET IDENTITY_INSERT
  3. Catch Me If You ... Can't Do Otherwise--转载
  4. html5 数据验证,【译】表单数据校验
  5. matlab求迟滞,MATLAB PI迟滞模型问题
  6. SQLite在字符串比较中的大小写问题
  7. nginx websocket 代理
  8. FIR数字滤波器的FPGA实现
  9. 计算机专业显示器英语,电脑显示器词汇 计算机英语词汇
  10. FPN网络详解——feature pyramid network
  11. 概率图模型(PGM):贝叶斯网(Bayesian network)初探
  12. c语言 程序设计一篇,用c语言编程任务br/请编写一个程序,从输入中读取一篇中文文 爱问知识人...
  13. 乐符识别matlab,基于DPP的自动音符切分识别研究
  14. 重标极差分析法matlab,重标极差(RS)分析法估计Hurst指数的有效性检验.doc
  15. Word章节自动编号+公式编号
  16. 2021年全国职业院校技能大赛网络搭建与应用之虚拟化配置答案
  17. electron 自动更新 热跟新
  18. C++类模板怎么写在单独的头文件和源文件中
  19. 【WT588F】网页上位机操作演示
  20. 博客园有一段时间登不上

热门文章

  1. 【264期】面试官问:Spring Boot 启动时自动执行代码方式有哪几种?解释一二!...
  2. 一些可以使你感兴趣的c语言简单练习
  3. 刘未鹏博客 http://mindhacks.cn/
  4. sofa协议服务器,撸了几天的sofa-tracer之后,我悟了
  5. PCIE LANE翻转和PN翻转(lane reversal and polarity)
  6. Maven插件之wagon-maven-plugin,远程自动化部署
  7. SDM845的音频路径分析
  8. 学网络安全基础需要记住的一些快捷键,和文件扩展名
  9. 如何 禁掉 Hyper-V 如何解决禁不掉 Hyper-V 的问题
  10. 深度学习完全攻略!(连载十二:SSD网络理解)