前段时间使用
leap motion
加入到我的VR程序当中,来代替手柄,但没有写交互。本以为可以使用手的模型来模拟鼠标点击与GUI发生交互,后来发现无法实现,原因之一是程序运行时画布Canvas始终会在摄像机的前面,而这个摄像机比较特殊,是VR摄像机,在VR世界里,我是无法看到UI,后来我找到了官方的example,我知道了必须自己设计三维物体来代替UI,并官方给出了一套交互引擎。这篇博客就是来总结这个交互引擎。
交互引擎允许开发者通过物理或者伪物理处理交互对象在你的VR应用中,交互引擎能帮你完成与物体的接触,抓住等交互。
API地址
:Interaction Engine
刚体(Rigidbody)
和至少一个碰撞体(Collider)
。交互管理器(Interaction Manager)
从unity中接收FixedUpdate
,并处理成为交互的内在逻辑,包括更新手和控制器数据以及交互对象数据(在场景中至少需要一个其中一个交互对象才能运行)。交互控制器(Interaction Controllers)
做与所有交互对象的实际内容(whether by picking them up, touching them, hitting them, or just being near them)。 在添加InteractionBehaviour
给对象之后,默认会发生:
第一个例子是介绍了几个不同对象在初次成为交互对象时的默认行为。
现在我们开始在unity中配置完整的交互。
Edit -> Project Settings -> Time
,设置为0.0111111 (每秒90帧)
。-4.905 on the Y axis instead of -9.81,Edit -> Project Settings -> Physics
.– VR Camera Rig
// no parent object, a child only of the ‘root’ of your scene hierarchy
—— VR Camera Object
// child of the rig object, this has the Camera component
——-Interaction Manager
// Have to have this in order for interactions to work!
————-Interaction Hand (Left)
// Interaction controllers must be children
————- Interaction Hand (Right)
// of their Interaction Manager.
配置步骤:
1. 新建场景,删除自带相机。在LeapMotion/Core/Prefabs
中把 LeapCameraRig
拖入场景。(应该是LMHeadMountedRig,集成了相机)
2. LeapMotion/Modules/Interaction/Prefabs
拖入Interaction Manager
3. 如果你需要配置其他玩家的对象,也就是说视角给到其他玩家。你需要添加组件
AttachmentHands
InteractionVRControllers
抓取如果您打算在Oculus Touch或Vive控制器上使用Interaction Engine,则需要配置项目的输入设置,然后才能使用控制器来抓取对象。转到您的输入管理器(编辑 - >项目设置 - >输入),并设置您想要用于左手和右手抓握的手柄轴。如果使用leap motion的话就不需要设置了。
实例显示了交互对象首次接收到InteractionBehaviour组件时的默认行为。
实例二展示了基础的UI,对按钮的点击和滑动。
Interaction Callbacks示例以一组交互对象为特征,它们共同组成一个基本的Transform Tool,用户可以在运行时使用它来操纵对象的位置和旋转。
看了这么多有趣的实例,在开始编码之前,先了解一下交互引擎编码技巧。
首先你需要知道脚本的执行顺序:更新顺序(FixedUpdate,PhysX,Update
)
FixedUpdate发生在物理引擎“PhysX”更新之前,并且是用户物理逻辑去的地方!
交互对象需要在运行时在两层之间切换,
一个存在于物体可以与你的手发生碰撞时(认为“已启用接触”),另一个存在于物体不能与你的双手发生碰撞时(当“禁用联系人”时,以及抓住物体时)。
用于为交互对象编写自定义脚本的标准工作流程如下所示:
1. 确保您的对象具有InteractionBehaviour
组件(或InteractionButton
或InteractionSlider
组件,每个组件都从InteractionBehaviour
继承)。
2. 将您的自定义脚本添加到交互对象并初始化对InteractionBehaviou
r组件的引用。
using Leap.Unity.Interaction;
using UnityEngine;
[RequireComponent(typeof(InteractionBehaviour))]
public class CustomInteractionScript : MonoBehaviour {
private InteractionBehaviour _intObj;
void Start() {
_intObj = GetComponent();
}
}
在运行时禁用/启用交互类型:
在运行时或之前禁用和启用悬停,接触或抓取是交互引擎的一流功能。你有两种方法可以做到这一点:
option1:使用控制器交互类型
InteractionController类
提供enableHovering,enableContact和enableGrasping属性
。将这些属性中的任何一个设置为true将立即激发相应交互类型的“结束”事件(仅限此对象),并防止任何控制器发生相应的交互作用到此交互对象。
option2:使用对象交互覆盖
InteractionBehaviour类
提供了ignoreHover,ignoreContact和ignoreGrasping属性
。将这些属性中的任何一个设置为true将立即激发相应交互类型的“结束”事件(仅限此对象),并防止任何控制器发生相应的交互作用到此交互对象。
我们来深入了解悬停、接触、抓取、扔等操作。
交互引擎中的悬停功能由两个相互关联的子系统组成,分别称为“悬停”和“主悬停”
。
Proximity feedback ("Hover"):
围绕交互控制器悬停点的悬停活动半径内的任何交互对象都将接收OnHoverBegin,OnHoverStay和OnHoverEnd回调,并将其isHovered状态设置为true,只要悬停控制器和交互对象都启用了悬停设置即可。交互对象也提供一个公共获取器来获得最接近的悬停交互控制器。一般来说,当编写关于邻近度的视觉和音频反馈脚本时,悬停信息很有用。
Primary Hover:
基本上,主要悬停是这样一种功能:当只有给定交互控制器的主要悬停对象可以被按下或以其他方式与该控制器交互时,将不可靠接口转换为可靠接口。这就是为什么示例2(基本用户界面)中的按钮面板在任何时候都只能按下一个按钮,即使您笨手笨脚地将整个手伸入面板。InteractionButton,InteractionToggle和InteractionSlider类都实现了这种主要悬停策略,以便生成更可靠的接口。
交互引擎中的接触由两个子系统组成:
接触骨骼
:它们是具有单个Collider的Rigidbodies以及包含用于手和控制器的其他接触数据的ContactBone组件。软接触
:当接触骨头脱离目标位置和旋转时 - 换句话说,当一只手或交互控制器在交互对象内部“过度”卡住自己时,它会激活。软接触本质上是替代物理引擎中的标准物理范式,将刚体作为完美的刚体处理。我们已经实现了一种精细调试的启发式方法,用于检测用户何时打算掌握交互对象。无论您是使用VR控制器还是使用VR,Interaction Engine中的抓取API都提供了一个通用接口,用于构建围绕抓取,释放和投掷的逻辑。
对象在两种相互排斥的移动模式之一下进行移动时:运动学或非运动学模式
。默认情况下,运动交互对象在抓握时将以运动学方式运动,而非运动交互对象在被掌握时将非运动地运动。当运动学移动时,交互对象的刚体位置和旋转被明确设置,有效地将对象传送到新的位置和旋转。这使得抓住的物体能够穿过它不能穿透的碰撞物。
当一个对象被一个移动的控制器持有时被移动时,一个特殊的回调会在对象移动后立即被触发,如果您希望修改对象在抓取时的移动方式,您应该订阅它。或者,您可以禁用交互对象上的moveObjectWhenGrasped设置,以防止它们完全抓住它们的移动(这将不再导致回调触发)。
当抓取物体被释放时,其速度和角速度由其类实现IThrowHandler接口
的对象控制。IThrowHandlers
在抓取过程中每帧都会接收更新,以便它们可以累积关于对象的速度和角速度数据 - 通常只需要最新的几帧数据。当对象最终被释放时,它们会得到一个OnThrow调用
,在默认实现(SlidingWindowThrow)
中,该调用根据对象速度的最近历史平均值设置对象的速度。在实践中,这导致用户投掷中更大的意向性。然而,如果你想创建一个不同的throw实现,你可以实现一个新的IThrowHandler
,并在任何交互对象上设置public throwHandler
来改变抛出行为的方式。
如果想好好学习到底是怎么实现这些酷酷的动作,研究example是最快的方式。当然,还得借助开发文档。祝学习愉快~~~