首页 > 技术文章 > VR中运动控制器的传送系统

tchivs 2019-06-14 14:39 原文

创建一个VRPawn

  1. 新建一个BluePrint,父类选择Pawn,我们命名为VRPawn,打开它。

  2. 添加一个Scene命名为CameraRoot

  3. 在CameraRoot节点下添加一个Camera

  4. 在DefaultSceneRoot下添加两个MotionContoller分别对应左手和右手,分别命名为“MotionController_L”和“MotionController_R”同时设置Visualization中的DisplayDeviceModel为True,DisplayModelSource为SteamVR。

  5. 设置右手的MotionSource为Right。

  6. 将VRPawn拖到场景中,并设置

添加并设置导航网格物体

首先要添加一个导航网格物体,它允许我们在导航网格物体覆盖的区域四处走动,要添加导航网格物体,先找到“模式”面板,选择“体积”,在下方找到“导航网格边界”(Nav Mesh Bounds Volume),然后将其拖到场景中。

如果看不到绿色的网格那说明你没开启显示

在其细节设置中找到“笔刷设置”(Brush Setting),改变其XYZ的值直到覆盖场景区域

使用导航网格边界时,所有对象都必须有碰撞组件,这样导航网格才知道哪些区域可以走动。

选中一个物体的静态网格

在这里面设置碰撞

如果还有一些区域是不希望用户可以到达的,可以添加“导航网格物体修改器体积”(Nav Mesh Modifier Volume)

会发现它所在的区域会破坏导航网格物体。所以我们可以调整其大小与位置到一些不希望用户过去的地方。

修改VRPawn

新建两个变量

变量名 类型 描述
bTeleport Bool 是否可传送
teleportLoc Vector 要传送的目标坐标

新建一个函数

这个函数主要的功能就是传送

函数名 getTPDestination

它需要两个参数

参数名 类型 描述
Position Vector 传送的位置坐标
ForwardVector Vector 朝向

连线

右击添加节点,输入并选择“LineTraceByChannel”。

这个节点会从我们所在位置向传送目的地发射出一条射线,用这种方法我们就能在按下某个键时计算出“teleportLocation”的位置。

将Postion与Start连接起来。

要得到End需要通过ForwareVector计算:

将Forware*10000后与Position相加。乘的系数即为射线的长度。

接下来要计算射线击中的对象

拖动“Out Hit” 并选择“Break Hit Result”来展开结构体。

只要我们击中对象就会得到这些信息,但我们只需要用到其中的一小部分信息。

首先要确定“Up的值”,所以我们要用到其中的“Normal”,然后对它使用点积,拖动后,搜索“dot product”:

将Z设置为1

接下来把结果和一个浮点数比较一下,判断点积结果是否比浮点数大。

将float设置为0.9

把判断结果赋值给"bTeleport"

接下来判断是否可以传送

从这里开始我们要使用导航网格物体,回到“Break Hit Result”,拖动“Location”,然后搜索“Project”,选择“ProjectPointToNavigation”

添加“teleportLoc”变量,并选择set,如果可以传送,则把ProjectedLocation赋给teleportLoc。

最后我们在场景中绘制一个调试圆柱体,方便显示传送点在哪里。在set后面继续添加引脚,输入“Draw Debug Cylinder”,将半径设置为50,设置颜色,把宽度改为2。

设置圆柱的高度,回到Break Hit Result”,拖动“Normal”输出引脚,搜索“ *”,它的值决定了圆柱体的高度,我将其设置为10。


接下来将这个Vector与“teleportLoc”相加,并连接Start和End。

记住“Draw Debug Cylinder”只能在开发中使用,打包项目时我们需要用一个更正式的对象来代替它,如一个静态网格体。

事件图表调用

最后我们需要在事件图表中调用函数。

找到Event Tick。

这个事件在场景中的每帧都会触发

定义传送函数

绑定控制器事件

推荐阅读