第一步:创建空的Unity项目,并依此导入 SteamVR 和 VRTK 插件包
(有顺序是因为VRTK是依赖于SteamVR的,顺序颠倒可能会出现error)
第二步:创建空物体并命名[ Manager](自定),添加脚本组件 VRTK_SDK_Manager;Manager下创建的子物体,并命名 [Setup](自定),添加脚本组件VRTK_SDK_Setup
第三步:添加SteamVR插件中的预制体[CameraRig]到Setup中做子物体,并删掉场景默认的MainCamera
在这里插入图片描述
第四步:选中Setup对象,Inspector中 QucikSelect 选择SteamVR,组件中的Objects会自动填充,默认Setup对象隐藏,运行的时候显示
第五步:创建两个空物体分别命名LeftController、RightController作为左右手柄控制器;选中Manager对象,在Inspector 组件中指定Scripts Aliases 对象
注:网上有些教程会这样讲:创建空物体,命名Manager(自定义)并添加脚本组件 VRTK_SDK_Manager,Project中搜索SDKSetups拖到Manager下做子物体,Manager上添加的脚本组件中参数Setups 点击“ ”新增项,并给其赋值SDKSetups下的SteamVR
该教程的做法与笔者上述的做法大同小异,只是该做法是引用预制体,其中包含多种设备的Setups而已,而我们的HTC Vive开发仅仅用到SteamVR
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 按下时速度倍乘
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 :头盔决定瞬移目标点
基本瞬移:场景中挂载脚本 VRTK_Basic Teleport 实现
挂载 VRTK_Dash Teleport 脚本,可以优化瞬移效果,不是硬生生的出现在目标点,而是像冲过去一样
适应高度的瞬移:场景中挂载脚本 VRTK_Height Adjust Teleport 实现
在这里插入图片描述
模拟过程的瞬移:场景中挂载脚本 VRTK_Basic Teleport 实现
头盔确定目标点的瞬移
创建空对象,命名TransForm Follower(自定义),挂载 VRTK_SDK Object Alias 脚本,参数选择 HeadSet 也就是跟随对象选择头盔
创建空对象,命名HeadSet(自定),挂载 VRTK_Pointer、VRTK_Bezier Pointer Renderer 和 VRTK_Transform Follow 脚本,前两个脚本实现发射曲射线,后者Follow实现射线跟随头盔,并且改变头盔的位置(即实现瞬移)
Pointer 要自定义手柄控制器,也就是使用哪个手柄触发头盔瞬移
用曲线实现此种瞬移比较好;如果选用直射线,射线有角度变化,目标点光标会变形
可以根据需要自行选择光标的形状、光标和射线路径是否显示
要特别注意 Transform Follow 中的赋值
10)双手操作
VRTK_MoveInPlace 脚本挂载到场景中,原地踏步就能实现移动,方向控制还需晃动头部,要是有万向走步机就更好了。
双手同时操作物体
VRTK_AxisScaleGrabAction 脚本实现双手缩放物体
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);
public VRTK_ControllerEvents vrtkcontroller 获取VRTK监听手柄事件的类
VRTK_ControllerEvents vrtkcontroller脚本在场景中[VRTK_Scripts]的RightControllerScriptAlias物体上
VRTK_ControllerEvents(定义后的变量名).TriggerPressed = void(object , ControllerInteractionEventArgs); 为手柄的圆盘监听的委托添加一个方法
controllerEvents.ButtonTwoPressed = 为菜单键添加事件
controllerEvents.TouchpadPressed = 为圆盘键添加事件
controllerEvents.TriggerPressed = 为扳机键添加事件
controllerEvents.TouchpadPressed =void((object,ControllerInteractionEventArgs) 其中第二个参数可以ControllerInteractionEventArgs.touchpadAxis的.x或.y可以获取到手指在圆盘上按下的二维位置
//监听圆盘键是否按下,返回bool值
VRTK_SDK_Bridge.GetControllerButtonState(SDK_BaseController.ButtonTypes.Touchpad,
SDK_BaseController.ButtonPressTypes.Press, VRTK_DeviceFinder.GetControllerReferenceForHand(SDK_BaseController.ControllerHand.Right))
//监听扳机键是否按下,返回bool值
VRTK_SDK_Bridge.GetControllerButtonState(SDK_BaseController.ButtonTypes.Trigger,
SDK_BaseController.ButtonPressTypes.Press, VRTK_DeviceFinder.GetControllerReferenceForHand(SDK_BaseController.ControllerHand.Right))
//监听菜单键是否按下,返回bool值(有可能参数是ButtoOne)
VRTK_SDK_Bridge.GetControllerButtonState(SDK_BaseController.ButtonTypes.ButtonTwo,
SDK_BaseController.ButtonPressTypes.Press, VRTK_DeviceFinder.GetControllerReferenceForHand(SDK_BaseController.ControllerHand.Right))
//监听手触摸在圆盘上的位置,返回Vector2值(轻轻触摸,不需要按下)
VRTK_SDK_Bridge.GetControllerAxis(SDK_BaseController.ButtonTypes.Touchpad, VRTK_DeviceFinder.GetControllerReferenceForHand(SDK_BaseController.ControllerHand.Right))