【幾行代碼】在VRTK中合併Teleport和Rotate操作


在VR的交互設計中,Teleport(閃現傳送)是最常用的距離移動手段,SnapRotation(視角旋轉)則是快速改變角度的手段(Rec Room中被大量使用),因此用戶如需要關注遠方某個物體則需要兩步操作——1 先Teleport 2 然後SnapRotation。姑且不說SnapRotation容易產生眩暈,對於交互心理學上來說,“少即是好”。所以有同學提出能不能把這兩個操作合併在一次操作。


之後【幾行代碼】專題的代碼都遵守乾淨原則:1 代碼量越少越好 2 不修改現有插件源代碼和美術資源 3 獨立成功能

依循乾淨原則的僞思路是

1 找到VRTK中Teleport的回調函數(Enter、Exit、Set)的信息,將Arrow箭頭畫在Enter期間

2 註冊Touchpad上的觸碰回調函數(TouchpadAxisChanged),改變Arrow的位置和記錄旋轉量

3 在Teleport觸發Set時將旋轉量賦予CameraRig(PS:這裏CameraRig的旋轉軸爲代表眼睛的Camera(eye))


首先製作一張Arrow的貼圖和一個Arrow的prefab,多幾個面片無所謂的話,可以用一個Cube快速完成





然後貼上代碼:

using UnityEngine;
using VRTK;

[RequireComponent(typeof(VRTK_Pointer))]
public class InteractionPoint : MonoBehaviour {

    VRTK_Pointer pointer;
    VRTK_ControllerEvents events; 

    [SerializeField]
    GameObject arrow;

    GameObject actualArrow;

    bool isEnter = false;
    float angleOffset = 0;

    private void Awake()
    {
        pointer = GetComponent<VRTK_Pointer>();
        pointer.DestinationMarkerEnter += onEnter;
        pointer.DestinationMarkerExit += onExist;
        pointer.DestinationMarkerSet += onSet;

        events = GetComponent<VRTK_ControllerEvents>();
        events.TouchpadAxisChanged += DoRightTouchpadTouched;

        actualArrow = Instantiate(arrow);
        actualArrow.SetActive(false);
    }

    private void onEnter(object sender, DestinationMarkerEventArgs e)
    {
        actualArrow.SetActive(true);
        Vector3 position = e.destinationPosition;
        actualArrow.transform.position = position;

        Vector3 forward = VRInteractController.CameraRig.position - position;
        actualArrow.transform.forward = new Vector3(forward.x, 0, forward.z);
        float startAngle = actualArrow.transform.eulerAngles.y;
        actualArrow.transform.eulerAngles = new Vector3(0, startAngle + angleOffset, 0);

        isEnter = true;
    }

    private void onExist(object sender, DestinationMarkerEventArgs e)
    {
        actualArrow.SetActive(false);
        isEnter = false;
        angleOffset = 0;
    }

    private void onSet(object sender, DestinationMarkerEventArgs e)
    {
        if (pointer.enableTeleport)
            VRInteractController.CameraRig.RotateAround(VRInteractController.Head.position, Vector3.up, angleOffset);
    }

    private void DoRightTouchpadTouched(object sender, ControllerInteractionEventArgs e)
    {
        if (isEnter)
        {
            angleOffset = e.touchpadAngle;
        }
    }

}


(轉載請註明出處http://blog.csdn.net/Poemlike_Studio)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章