1
2
3
4
5
6
  • AR开发
7
8
  • 系统优化与发布

新建目录

发布时间:2020-08-22 22:59   发布人:焦卫峰   浏览次数:399

1.VR环境搭建

第一步:创建空的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

2.VRTK使用

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);

3. VRTK_ControllerEvents类

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))