UnityでVRChatみたいなタッチパッド移動をする（VIVE コントローラ編）

こんにちは、ZeniZeniです。
VR空間の移動方法って色々ありますけど、個人的にはタッチパッドでぐりぐり動くのが好きです。
自分のゲームで実装しようと思って方法を探したら、なかなかいいのが見つからなかったので自作しました。

# 動作環境
-Unity 2018.2.15f1
-SteamVR v1.2.3

#使用するコード
```c#:TouchPadMove
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TouchPadMove : MonoBehaviour
{

    private SteamVR_TrackedObject trackedObj;
    private SteamVR_Controller.Device Controller
    {
        get { return SteamVR_Controller.Input((int)trackedObj.index); }
    }

    public enum MoveType
    {
        Walk,
        WalkOnClick,
        RotateOnClick,
    }

    public MoveType moveType;

    [SerializeField]
    private float Speed;
    [SerializeField]
    private Vector3 ChangeAngle;

    [SerializeField]
    private GameObject CameraRig;
    [SerializeField]
    private GameObject CameraEye;


    #region TouchPadProperty
    private bool TouchPadUp;
    private bool TouchPadDown;
    private bool TouchPadLeft;
    private bool TouchPadRight;
    #endregion


    void Awake()
    {
        trackedObj = GetComponent<SteamVR_TrackedObject>();
    }

    void FixedUpdate()
    {
        if (moveType == MoveType.Walk)
        {
            if (Controller.GetAxis() != Vector2.zero)
            {
                Walk(Controller.GetAxis());
            }
        }
        else if (moveType == MoveType.WalkOnClick)
        {
            if (Controller.GetPress(SteamVR_Controller.ButtonMask.Touchpad))
            {
                if (Controller.GetAxis() != Vector2.zero)
                {
                    Walk(Controller.GetAxis());
                }
            }
        }
        else if (moveType == MoveType.RotateOnClick)
        {
            if (Controller.GetPressDown(SteamVR_Controller.ButtonMask.Touchpad))
            {
                Rotate();
            }
        }


        if (Controller.GetAxis() != Vector2.zero)
        {
            TouchPadPositionCheck(Controller.GetAxis());
        }
    }


    public Vector2 RotateMatrix(Vector2 TouchPosition)
    {
        float angle = (-CameraEye.transform.localEulerAngles.y - CameraRig.transform.localEulerAngles.y) * Mathf.Deg2Rad;
        float x = TouchPosition.x * Mathf.Cos(angle) - TouchPosition.y * Mathf.Sin(angle);
        float y = TouchPosition.x * Mathf.Sin(angle) + TouchPosition.y * Mathf.Cos(angle);

        Vector2 RotatedVector = new Vector2(x, y);

        return RotatedVector;
    }

    private void TouchPadPositionCheck(Vector2 TouchPosition)
    {
        float degree = Mathf.Atan2(TouchPosition.x, TouchPosition.y) * Mathf.Rad2Deg;

        if (-30 < degree && degree < 30) TouchPadUp = true;
        else TouchPadUp = false;

        if (-180 < degree && degree < -150 || 150 < degree && degree < 180) TouchPadDown = true;
        else TouchPadDown = false;

        if (30f < degree && degree < 150f) TouchPadRight = true;
        else TouchPadRight = false;

        if (-150f < degree && degree < -30f) TouchPadLeft = true;
        else TouchPadLeft = false;
    }


    private void Walk(Vector2 TouchPosition)
    {
        Vector2 RotatedVector = RotateMatrix(TouchPosition);
        Vector3 MovePosition = new Vector3(RotatedVector.x * Speed, 0, RotatedVector.y * Speed);
        CameraRig.transform.position += MovePosition;
    }

    private void Rotate()
    {
        var postPos = CameraEye.transform.position;
        if (TouchPadRight)
        {
            CameraRig.transform.localEulerAngles += ChangeAngle;
        }
        if (TouchPadLeft)
        {
            CameraRig.transform.localEulerAngles -= ChangeAngle;
        }
        var currentPos = CameraEye.transform.position;
        CameraRig.transform.position += (postPos - currentPos);
    }
}
```
#使い方
SteamVRをプロジェクトにインポートして、シーンに[CameraRig]と[Status]を置きます。
そして、[CameraRig]階層下のcontrollerに上のTouchPadMoveスクリプトをアタッチします。
![bandicam 2019-01-20 02-55-28-498.jpg](https://qiita-image-store.s3.amazonaws.com/0/281560/e04e5943-6595-b44e-e33f-ac33284ebe99.jpeg)
CameraRig、CameraEyeにそれぞれ[CameraRig]、Camrera(eye)をアタッチしてください。

MoveTypeでWalkを選ぶと、タッチパッドを触るだけで移動します。
WalkOnClickを選ぶと、タッチパッドを押して移動します。
RotateOnClickを選ぶと、タッチパッドの右半分をクリックすると右に回転、左半分をクリックすると左に回転します。

Speedで移動速度が変わります。
ChangeAngleで回転時の回転角度が変わります。
どちらも最初0なので、適当な値を入れてください。
#開発、執筆にあたり、下記のサイト様を参考、引用させていただきました。
　
1. [[FRAME SYNTHESE] Unity + HTC Vive 開発メモ](https://framesynthesis.jp/tech/unity/htcvive/)