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