美文网首页一起来玩VR\ARAR/VR/MRVR
一个前线开发者的VRTK笔记(一)

一个前线开发者的VRTK笔记(一)

作者: Angeladaddy | 来源:发表于2017-06-02 08:47 被阅读299次
    Paste_Image.png

    前言:VRTK官方插件的DOCUMENT.MD文档是英文,看起来略吃力。其教程是油管视频需要翻墙且全英文。网上的教程基本都是只覆盖到场景搭建和简单交互。远远不够实际开发需要。本人经过一段时间开发之后,把此插件中的精华部分拿出来整理以下。希望能帮到广大VR开发者。本文全干货,无废话,下面开始。

    1. 场景搭建


    1.1 场景中拖入StreamVR的[CameraRig]预制件(VRTK依赖SteamVR)
    1.2 建立一个空物体命名比如[VRTK],添加VRTK_SDKManager组件,根据需要选择开发平台,此处不需要一个一个选,只需要下拉选择QuickSelectSDK,和最下面的AutoPopulateLinkedObjects就行,最后的ScriptAlais...需要自己指定。

    tips: 注意每建立新场景,这个步骤必须从头做一遍,不能把别的场景里的prefab拿进来直接用。

    Paste_Image.png
    1.3 [VRTK]下面再放置两个空物体(左右手控制器),都添加VRTK_ControllerEvents组件,此组件是控制器交互基础组件,必须添加 Paste_Image.png

    2. 物体交互

    tips: 可交互物体至少要有collider


    2.1 激光束和瞬移-官方文档

    • 在两个手柄上添加VRTK_SimplePointer或者VRTK_BezierPointer。一个是直线,一个是贝兹曲线。勾选Enable teleport.
    • 在CameraRig上添加VRTK_BasicTeleport

    tips:

    • SimplePointer/BezierPointer发送以下事件:
     GetComponent<VRTK_SimplePointer>().DestinationMarkerEnter += new DestinationMarkerEventHandler(DoPointerIn);
    GetComponent<VRTK_SimplePointer>().DestinationMarkerExit += new DestinationMarkerEventHandler(DoPointerOut);
    GetComponent<VRTK_SimplePointer>().DestinationMarkerSet += new DestinationMarkerEventHandler(DoPointerDestinationSet);
    

    并传递以下参数:

            public float distance;
            public Transform target;
            public RaycastHit raycastHit;
            public Vector3 destinationPosition;
            public bool forceDestinationPosition;
            public bool enableTeleport;
            public uint controllerIndex;
    
    • SimplePointer上附带的teleporter功能只能在平面上移动,如果想要动Y轴,请使用VRTK_HeightAdjustTeleport.
    • 所有瞬移组件会发送TeleportingTeleported事件,传递以下参数(和上面pointer参数基本一致):

    float distance - The distance between the origin and the collided destination.
    Transform target - The Transform of the collided destination object.
    RaycastHit raycastHit - The optional RaycastHit generated from when the ray collided.
    Vector3 destinationPosition - The world position of the destination marker.
    Quaternion? destinationRotation - The world rotation of the destination marker.
    bool forceDestinationPosition - If true then the given destination position should not be altered by anything consuming the payload.
    bool enableTeleport - Whether the destination set event should trigger teleport.
    uint controllerIndex - The optional index of the controller emitting the beam.

    - ```VRTK_BodyPhysics```组件加入玩家身体与游戏世界的交互,并且决定其掉落物理特性 [文档](https://github.com/thestonefox/VRTK/blob/master/DOCUMENTATION.md#body-physics-vrtk_bodyphysics)。可根据需要加入
    
    > ![Paste_Image.png](http:https://img.haomeiwen.com/i1431816/c8a62d1f26cf23b1.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 
    - ```VRTK_DashTeleport``` 是一种类似往前冲的特殊瞬移效果,取代默认的“眼前一黑”效果,个人以为体验比较好
    - 如果场景中有一些物体不想设置为瞬移对象,那么需要添加```VRTK_PolicyList```组件,并在Teleport组件中指定。```VRTK_PolicyList```使用物体的```tag,脚本,或者layer```来指定忽略对象  
    ![Paste_Image.png](http:https://img.haomeiwen.com/i1431816/0893d3fc0d41cf77.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
    ![Paste_Image.png](http:https://img.haomeiwen.com/i1431816/f56cd56a7a7fd2a0.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
    - ```VRTK_PlayAreaCursor```组件为玩家PlayArea设置了一个体积,并且只允许瞬移到那些能够容纳此体积的物体。这样,墙壁、窄的通道等物体由于其体积小于Playarea,因此不能瞬移。示范场景```012_Controller_PointerWithAreaCollision```。 
    ![Paste_Image.png](http:https://img.haomeiwen.com/i1431816/c8b990497802c6a4.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
    
    
    
    
    ##2.2 碰触
    手柄上添加```VRTK_InteractTouch```组件。在物体上添加```VRTK_InteractableObject```组件。可以设置高亮颜色,设置为黑色则不高亮。
    > tips:
    1. ```VRTK_InteractableObject```组件是可交互物体基础组件。场景中任何可交互物体都必须要有这个组件。
    2. 手柄上的```VRTK_InteractTouch```发送```ControllerTouchInteractableObject ```和```ControllerUntouchInteractableObject```事件,传递两个参数:(int:控制器id,gameobject:被接触的物体)
    
    ##2.3 抓取
    1. 手柄上添加```VRTK_InteractGrab```脚本,此脚本依赖```VRTK_InteractTouch```,所以无需再添加。此脚本还依赖```VRTK_ControllerActions```。
    2. 需要抓取的物体上添加```VRTK_InteractableObject```组件,或者直接写一个类继承它。并设置```isGrabable=true```。
    >tips:```VRTK_InteractableObject```组件我认为是这个插件最核心的组件,抓取的默认按键是手柄两侧的grip键
    1. 被抓取的物体上必须要有Collider,其它组件如rigidbody和```VRTK_FixedJointGrabAttach(默认附着方式)```等会在需要时自动添加。
    3.  ```Hold Button To Grab```设置为true时,则需要一直按下抓取键,松开物体即掉落。
    4. grabOverrideButton和useOverrideButton分别用来制定抓取和use键
    5. 如果要在抓取时隐藏手柄,添加```VRTK_InteractControllerAppearance```组件。
    7. ```VRTK_InteractableObject```脚本如果勾选了可以抓取,则此脚本在手柄第一次抓取物体时将会自动给物体添加```VRTK_FixedJointGrabAttach```和```rigidbody```组件,这是默认的抓取方式,此方式可以override。
    8. 手柄上的```VRTK_InteractGrab```组件发射```ControllerGrabInteractableObject```和```ControllerUngrabInteractableObject```事件。同样传递两个参数:(int:控制器id,gameobject:被接触的物体)
    
    
    ## 2.4 使用
    > tips: 使用(use)的默认按键是trigger键
    1. 手柄上除了上述组件外,再添加```VRTK_InteractUse```组件
    2. 物体上同样必须添加```VRTK_InteractableObject```组件
    4.  is Useable,Hold Button To Use决定是否可以使用物体。Use Only If Grabbed只有在抓取后可以使用物体。Pointer Activates Use Action使得可以用射线使用物体,前提条件是去掉Hold Button To Use勾选。
    2. 使用use功能:按下trigger键(可自定义)调用物体上的use方法,此方法是一个虚方法可以很方便的重写。比如拿起一支枪并开始射击。参见Gun脚本 核心代码:
    > ```
    public override void StartUsing(GameObject usingObject)
          {
              base.StartUsing(usingObject);
             //自定义实现
          }
    public override void StopUsing(GameObject usingObject)
          {
              base.StopUsing(usingObject);
               //自定义实现
          }
    protected void Start()
          {
             //正常使用Start()方法
          }
    protected override void Update()
          {
            //复写Update()方法
              base.Update();            
          }
    

    秘诀:除了复写StartUsing方法(这种方式不太灵活)外,还可以监听手柄上VRTK_InteractUse组件的ControllerUseInteractableObject/ControllerUnuseInteractableObject事件,此事件发送两个参数:控制器index和使用的物体。前述的touch/grab都有类似事件发送,可以很方便的监听

    控制器碰触、抓取、使用事件示例:

                //监听两个手柄的碰触事件
                controllerTouchScripts =GetComponentsInChildren<VRTK_InteractTouch>();
                foreach (var item in controllerTouchScripts)
                {
                    item.ControllerTouchInteractableObject += (s, e) => {//事件处理};
                    item.ControllerUntouchInteractableObject += (s, e) => { //事件处理};
                }
                //监听两个手柄的抓取事件
                controllerGrabScripts = GetComponentsInChildren<VRTK_InteractGrab>();
                foreach (var item in controllerGrabScripts)
                {
                    item.ControllerGrabInteractableObject += (s, e) => {//事件处理};
                    item.ControllerUngrabInteractableObject += (s, e) => { //事件处理};
                }
                //监听两个手柄的使用事件
                controllerUseScripts = GetComponentsInChildren<VRTK_InteractUse>();
                foreach (var item in controllerUseScripts)
                {
                    item.ControllerUseInteractableObject += (s, e) => {//事件处理};
                    item.ControllerUnuseInteractableObject += (s, e) => { //事件处理};
                }
    

    3. UI-官方文档


    UnityUI交互:

    • 手柄上添加VRTK_UIPointer组件和VRTK_SimplePointer组件,3dCanvas上添加VRTK_UICanvas组件即可

    tips:

    • 也可在头盔上添加VRTK_UIPointer组件和VRTK_SimplePointer组件,这样有了所谓的“凝视”功能,只不过此时要交互的话需要需要指定一个手柄:
      Paste_Image.png
    • UI事件handle:
    GetComponent<VRTK_UIPointer>().UIPointerElementEnter += VRTK_ControllerUIPointerEvents_ListenerExample_UIPointerElementEnter;
    GetComponent<VRTK_UIPointer>().UIPointerElementExit += VRTK_ControllerUIPointerEvents_ListenerExample_UIPointerElementExit;
    GetComponent<VRTK_UIPointer>().UIPointerElementClick += VRTK_ControllerUIPointerEvents_ListenerExample_UIPointerElementClick;
    GetComponent<VRTK_UIPointer>().UIPointerElementDragStart += VRTK_ControllerUIPointerEvents_ListenerExample_UIPointerElementDragStart;
    GetComponent<VRTK_UIPointer>().UIPointerElementDragEnd += VRTK_ControllerUIPointerEvents_ListenerExample_UIPointerElementDragEnd;
    

    手柄UI交互

    - 手柄tips:在手柄下拖入ControllerTooltips预制件作为子物体即可

    Paste_Image.png

    - 手柄环形菜单:在手柄下拖入RadialMenu预制件作为子物体即可

    Paste_Image.png

    tips:

    • public bool isShown;决定是否显示环形菜单,和public bool executeOnUnclick;配合使用可以在用户触摸touchpad时才显示环形菜单。

    为了方便广大程序猿同志,VRTK对一些常见交互物体进行了封装,下面我们来看一下:

    1. Door (VRTK_Door)
      直接生成一扇可以打开的门,简单到只需要指定门物体和把手物体(不指定把手则直接将门本身作为交互物体)
    Paste_Image.png

    忽略我的这扇门的轴点。。。,应该在建模软件里调整好轴点

    相关文章

      网友评论

        本文标题:一个前线开发者的VRTK笔记(一)

        本文链接:https://www.haomeiwen.com/subject/dqkvottx.html