VRTK使用
参考文档:https://blog.csdn.net/qq_25601345/article/details/78497537?tdsourcetag=s_pcqq_aiomsg#_Toc31475
VRTK:3.2.1 版本 Steam VR:Assets Store下载
1、手柄发射射线
- 手柄控制器挂载两个脚本:VRTK_Pointer 射线发射脚本 和 VRTK_Stratight Pointer Renderer
直
射线渲染脚本(或 VRTK_Bezier Pointer Renderer曲
射线脚本组件,射线的模型和目标点模型等参数可自定义),VRTK_Pointer脚本中指定Pointer Render类型;
2、手柄基本交互事件(触摸、抓取和使用)
给手柄控制器添加 VRTK_Controller_Events 脚本(手柄事件机制必需);
- 根据需要添加以下脚本组件 :
VRTK_Interact Touch(触碰)
VRTK_Interact Grab(抓取注:指定默认的抓取按键 Grab Button
)
VRTK_Interact Use(使用注:指定默认的使用按键 Use Button
)
一般 Events、Touch、Grab、Use 这几个脚本都给控制器添加上
抓取和使用脚本中,按钮若指定默认值,被交互物体所挂脚本中按钮可默认不更改;按钮若不指定,被交互物体所挂脚本中按钮要自定义;否则,被交互物体不能响应手柄的事件
3、物体抓取
- 物体能够被抓取的条件*
需要有Rigidbody
和Collider
组件,
挂载 VRTK_Interactable Object 脚本才可以响应手柄的交互,Touch Highlight Color 调整触碰时的高亮颜色,
如果不给物体添加抓取方式,默认使用固定关节抓取方式:VRTK_FixedJointGrabAttach,
挂载VRTK_ Outline Object Copy Highlighter脚本使物体 外轮廓 呈现高亮,默认整体高亮
注:
- VRTK_Interactable Object脚本中的 Is Grabable(Is Usable) 默认是不勾选的,如果想要该物体能够被抓取,需要勾选该选项
- 如果想点击抓取按钮之后就拿到物体,而不是一直按着按钮,取消勾选 Hold Button To Grab 即可
- 挂载 VRTK_Swap Controller Grab Actions 脚本实现物体可以左右手交换
七种抓取方式:
VRTK_FixedJointGrabAttach 固定关节抓取(系统默认方式)
VRTK_SpringJointGrabAttach 弹簧关节抓取(手柄和被抓取物体之间弹簧链接效果,比如抽屉的弹性效果)
VRTK_CustomJointGrabAttach 自定义关节抓取(添加所需类型的Joint组件,并指定给自定义关节参数 Custom Joint)
VRTK_TrackObjectGrabAttach 对象追踪抓取(被抓取物体跟踪手柄,受外力阻挡时不会掉落)
VRTK_ClimbableGrabAttach 可攀爬抓取(实现手抓物体可攀爬效果),另外需要在场景上挂载 VRTK_Player Climb 脚本
VRTK_RotatorTrackGrabAttach 旋转体抓取 (效果和弹簧关节相似,比如门旋转的弹性效果,笔者猜测钟摆效果也可)
VRTK_ChildOfControllerGrabAttach 作为控制器子物体(抓取物体成为手柄控制器模型子物体,射箭的典型例子)
4、物体使用(第25个例子未研究,一些物体的使用)
手柄控制器添加 VRTK_Interact Use 脚本,
被使用物体添加自定义脚本,继承VRTK_Interactable Object 类(勾选 Is Usable),重写该类的 StartUsing () { //自定义“使用”功能 } 和 StopUsing () 方法
注:
- 若多个物体组成被交互对象,其中有使用对象,脚本挂在父容器上即可
射线使用物体:
勾选 Use Options 中的 Pointer Activates Use 实现
5、物体交互手柄震动
TriggerHapticPulse() 函数实现手柄震动:
- 参数:
index:手柄索引
strength:震动强度
duration:持续时间
旧版本VRTK中使用的是 VRTK_Controller Action.TriggerHapticPulse(float strength);
较新版本中使用的是 VRTK_SharedMethods.TriggerHapticPulse
( int index ,float strength,float duration);
以上两种方法逐渐被弃用,使用 VRTK_ControllerHaptics.TriggerHapticPulse(controllerReference, 5000f);
//最简单的手柄碰撞震动脚本,脚本挂载Stick物体上,VRTK_ChildOfControllerGrabAttach 抓取方式
public class Stick : VRTK_InteractableObject{
//控制器引用(即 Left/RightCntroller)
private VRTK_ControllerReference controllerReference;
public override void Grabbed(VRTK_InteractGrab currentGrabbingObject = null)
{
base.Grabbed(currentGrabbingObject);
//获取当前抓取物体的控制器
controllerReference = VRTK_ControllerReference.GetControllerReference(currentGrabbingObject.controllerEvents.gameObject);
}
public override void Ungrabbed(VRTK_InteractGrab previousGrabbingObject = null)
{
base.Ungrabbed(previousGrabbingObject);
controllerReference = null;
}
private void OnCollisionEnter(Collision collision)
{
if (VRTK_ControllerReference.IsValid(controllerReference) && IsGrabbed())
{
//手柄震动函数
VRTK_ControllerHaptics.TriggerHapticPulse(controllerReference, 5000f);
}
}
}
6、TouchPad 控制主角移动、添加自定义菜单
1、手柄控制器上挂载 VRTK_Touchpad Control 脚本组件控制圆盘
- 参数说明:
Device For Direction:选择哪个设备的方向为准
Disable Other Controllers On Active:如果勾选,将其他监听TouchPad事件的函数都禁用掉
Affect On Falling:当下落的时候可以继续控制
Primary Activation Button:哪个按钮启动控制
Active Modifier Button:激活控制行为的按钮
- 真正实现圆盘控制主角移动,还需要 VRTK_SlideObjectControl Action 脚本设置轴偏移量,并且要指定 Object Controller Scripts
Maximum Speed :触摸 TouchPad 时最大移动速度
Speed Multilier:TouchPad 按下时速度倍乘
2、RadialMenu 预制体,VRTK_Radial Menu 菜单设置脚本 和 VRTK_Radial Menu Controller 菜单控制脚本
- VRTK_Radial Menu 参数说明:
Buttons:设置按钮数量,内部元素设置按钮的 图片样式 和 添加事件监听
Button Prefab:按钮面板的样式(默认环形)
Button Thickness:环的宽度
Offset Distance:按钮间距
Offset Rotation:按钮旋转的方位角
Rotate Icons:是否旋转菜单图标来适应菜单朝向
Icon Margin:图标到边缘距离
Hide On Release:释放时隐藏
Execute On Unclick:释放按钮时是否执行事件
Base Haptic Strength:选择不同按钮时的震动
7、对象排除/包含列表 (VRTK_Policy List)
以瞬移为例,如下图
VRTK_Policy List 属性解析:
- Operation为Ignore/Include(忽略),Types为Tag(标签)和Script(脚本)等,Element里面设置了ExcludeTeleport,这样设置,如果游戏物体上挂载有 ExcludeTeleport 这个名称的脚本或是游戏物体的标签为ExcludeTeleport,都不能瞬移到这个游戏物体上
- 举个栗子,现在要在一个房间中实现瞬移,并且你想限制只能够在地板上瞬移,不能瞬移到高处,比如桌子、柜子上什么的;此时添加 Policy List 脚本,Operation选择 Include 地板 ground,或者 Operation 选择 Ignore 除地板之外的所有物体
8、射线与UI交互 (VRTK_UI Pointer、VRTK_UI Canvas)
注:实现射线与UI交互,需要给控制器添加 VRTK_UI Pointer 脚本
三种UI交互方式:
- 普通UGUI:Canvas 的Render Mode设置为 World Space ;挂载脚本 VRTK_UICanvas
- 键盘UI:添加脚本 VRTK_UICanvas 和 UI_KeyBoard ,在每个按键Button上要绑定点击事件 ClickKey
UI_KeyBoard 脚本即控制键盘输入的代码:
public class UI_Keyboard : MonoBehaviour
{
private InputField input; //输入框
private void Start()
{ //获取输入框组件
input = GetComponentInChildren<InputField>();
}
//点击键盘上的字母时执行
public void ClickKey(string character)
{
input.text += character;
}
//点击空格时执行
public void Backspace()
{ //如果输入文本长度不为零
if (input.text.Length > 0)
{ //文本分割,去掉最后一位
input.text = input.text.Substring(0, input.text.Length - 1);
}
}
//点击Enter键时执行
public void Enter()
{ //提示语
VRTK_Logger.Info("You've typed [" + input.text + "]");
//输入框文本清空
input.text = "";
}
}
- 拖拽UI:添加脚本 VRTK_UIDropZone
9、瞬移
- 四种瞬移方式:
VRTK_Basic Teleport :基本的瞬移
VRTK_Height Adjust Teleport :高度适应的瞬移,继承基本瞬移的功能
VRTK_Dash Teleport :模拟过程的瞬移,继承基本瞬移和高度适应的瞬移
VRTK_Transform Follow :头盔决定瞬移目标点
1、基本瞬移:场景中挂载脚本 VRTK_Basic Teleport 实现
挂载 VRTK_Dash Teleport 脚本,可以优化瞬移效果,不是硬生生的出现在目标点,而是像冲过去一样
2、适应高度的瞬移:场景中挂载脚本 VRTK_Height Adjust Teleport 实现
3、模拟过程的瞬移:场景中挂载脚本 VRTK_Basic Teleport 实现
4、头盔确定目标点的瞬移
- 创建空对象,命名TransForm Follower(自定义),挂载 VRTK_SDK Object Alias 脚本,参数选择 HeadSet 也就是跟随对象选择头盔
- 创建空对象,命名HeadSet(自定),挂载 VRTK_Pointer、VRTK_Bezier Pointer Renderer 和 VRTK_Transform Follow 脚本,前两个脚本实现发射曲射线,后者Follow实现射线跟随头盔,并且改变头盔的位置(即实现瞬移)
Pointer 要自定义手柄控制器,也就是使用哪个手柄触发头盔瞬移
笔者测试,用曲线实现此种瞬移比较好;如果选用直射线,射线有角度变化,目标点光标会变形
可以根据需要自行选择光标的形状、光标和射线路径是否显示
要特别注意 Transform Follow 中的赋值
10、双手操作
-
VRTK_MoveInPlace 脚本挂载到场景中,原地踏步就能实现移动,方向控制还需晃动头部,要是有万向走步机就更好了。
-
双手同时操作物体
1、VRTK_AxisScaleGrabAction 脚本实现双手缩放物体
2、VRTK_ControlDirectionGrabAction 脚本实现双手同时拿起同一个物体,一般是长物体
11、射线作为手柄扩展
- VRTK_Pointer 脚本组件中的 Interact With Objects 属性:如果勾选该属性,那么射线就相当于手柄控制器的扩展;已知只有当手柄接触到物体时,才会有高亮显示(如果你想),若实现手柄接触物体也能高亮显示,需勾选该选项,让射线代替手柄去接触物体即可实现,,,当然被选中物体要有Interactable Object 脚本,且勾选Pointer Active Use 的选项
12、获取手柄按键
//获取右手手柄的引用
rightControllerReference = VRTK_ControllerReference.GetControllerReference(VRTK_DeviceFinder.GetControllerRightHand(true));
//获取手指是否触摸手柄圆盘,返回Bool值
isTouchPadTouch = VRTK_SDK_Bridge.GetControllerButtonState(SDK_BaseController.ButtonTypes.Touchpad, SDK_BaseController.ButtonPressTypes.Touch, rightControllerReference);
isTouchPadUp = VRTK_SDK_Bridge.GetControllerButtonState(SDK_BaseController.ButtonTypes.Touchpad, SDK_BaseController.ButtonPressTypes.TouchUp, rightControllerReference);