LoginSignup
8
6

More than 3 years have passed since last update.

UnityのSteamVR plugin(2.6.1)を使ってVRChatぽい移動を再現(Valve Index)

Last updated at Posted at 2020-08-06

 Unity上でネイティブVR空間を作ってみようと思いました。ちなみに空間を作り上げてVR体験するだけだったら、VRChatclusterでワールドを作った方が手軽だし共有もしやすいのでおすすめです。

  • Unity Editor ... 2019.2.21f1
  • SteamVR plugin ... 2.6.1
  • 使用デバイス ... Valve Index

まずはプロジェクト作成

image.png

SteamVR pluginのimport

image.png

image.png

 よくわからないけど脳死で「Accept All」を押します。(いいのか?)

image.png

 以降、ずっと出てくるこのウィンドウは無視します。特に弊害がないので。(いいのか?)

カメラプリファブの設置

image.png

 Assets > SteamVR > Prefabsにある[Camera Rig]のプリファブをヒエラルキーに置きます。これがプレイヤーの頭となります。元からあったMain Cameraは削除します。

image.png

 これは本質的には必要ない作業ですが、地平線だけだと味気ないので、PlaneとSphereを設置しています。

 再生ボタンを押します。

image.png

 何も考えずにYesを押します。

image.png

 何も考えずにSave and Generateを押します。

image.png

 Save

image.png

 もう一度再生ボタンを押せば、これだけでもうVR空間の中を歩き回れます。しかし、コントローラで歩き回れるようにもしたいです。

コントローラの設定

image.png

 ここでSteamVR Input

image.png

 これらの文字の羅列の意味は後で分かってきますので、とりあえずOpen building UI

image.png

 編集。

image.png

 ここで、先程の文字の羅列が、コントローラの入力と対応したものであったことがわかります。VRChatライク(非Holoport)な移動をするためには、十字スティックの入力を2次元座標として受け取る必要がありますが、デフォルトの配列ではそうはなっていないようなので、追加します。

image.png

Thumb Stickの+ボタンを押して「ジョイスティック」を追加します。

image.png

 ここで「位置」にアクションを割り当てる……と行きたいところですが、何も選択できない状態になっているはずです。位置のデータ形式はVector2ですが、Vector2を入力として受け取るアクションが用意されていないためです。という訳で、先程のSteamVR Inputに戻ってコマンドを追加します。

image.png

image.png

 +ボタンでアクションを追加し、適当な名前にします(ここでは仮にMoveとしています)。また、Typevector2にします(ここ重要)。変更が終わったらSave and generateを忘れずに。

image.png

 今度は選択できるようになりました。

image.png

image.png

 割り当てた後は、「デフォルトバインドの置換」から「保存」を忘れずに。

スクリプトの作成

 下のようなスクリプトを用意します。ここでは仮にMove.csとしておきます。

using UnityEngine;
using Valve.VR;

public class Move : MonoBehaviour
{
    private SteamVR_Action_Vector2 move = SteamVR_Actions._default.Move;
    float MoveSpeed = 0.1f;

    private void Start()
    {
    }

    private void Update()
    {
        Vector2 pos = move.GetLastAxis(SteamVR_Input_Sources.LeftHand);
        transform.position += transform.forward * pos.y * MoveSpeed;
        transform.position += transform.right * pos.x * MoveSpeed / 5;
    }
}

image.png

 [CameraRig]にアタッチします。

 これで左コントローラを動かせばその通りにカメラ(=プレイヤー)が動くようになったと思われますが、少し不自然だと思います。なぜかというと、頭の向きと進行方向が一致していないからです。[CameraRig]はあくまで体の向きであり、実際の頭の向きはその下にあるCameraというオブジェクトだからです。ちゃんと見ている方向を基準にするべく、以下のようなコードにします。

using UnityEngine;
using Valve.VR;

public class Move : MonoBehaviour
{
    private SteamVR_Action_Vector2 move = SteamVR_Actions._default.Move;
    float MoveSpeed = 0.1f;
    private GameObject Head;

    private void Start()
    {
        Head = GameObject.Find("Camera");
    }

    private void Update()
    {
        Vector2 pos = move.GetLastAxis(SteamVR_Input_Sources.LeftHand);
        this.transform.position += Head.transform.forward * pos.y * MoveSpeed;
        this.transform.position += Head.transform.right * pos.x * MoveSpeed / 5;
    }
}

 しかし、これでもまだ片手落ちで、これだと頭が少しでも見上げていたり見下ろしていたりすると空中方向の移動が発生してしまいます。コライダーとか重力の処理の話はおいといて、とりあえずこのサンプルをそれっぽく動かすために、y座標は常に0にするように追加処理を加えます。

using UnityEngine;
using Valve.VR;

public class Move : MonoBehaviour
{
    private SteamVR_Action_Vector2 move = SteamVR_Actions._default.Move;
    float MoveSpeed = 0.1f;
    private GameObject Head;

    private void Start()
    {
        Head = GameObject.Find("Camera");
    }

    private void Update()
    {
        Vector2 pos = move.GetLastAxis(SteamVR_Input_Sources.LeftHand);
        transform.position += Head.transform.forward * pos.y * MoveSpeed;
        transform.position += Head.transform.right * pos.x * MoveSpeed / 5;
        Vector3 loc = transform.position;
        loc.y = 0;
        transform.position = loc;
    }
}

回転方向の刻み

 ジョイスティックだけだと方向転換ができないので、VRChatライクに右コントローラのジョイスティックに回転を割り当てます。

image.png

 ジョイスティックの左入力と右入力についてはデフォルトで設定があるので、それをそのまま使います。以下のようなコードにします。

using UnityEngine;
using Valve.VR;

public class Move : MonoBehaviour
{
    private SteamVR_Action_Vector2 move = SteamVR_Actions._default.Move;
    private SteamVR_Action_Boolean left = SteamVR_Actions._default.SnapTurnLeft;
    private SteamVR_Action_Boolean right = SteamVR_Actions._default.SnapTurnRight;
    float MoveSpeed = 0.1f;
    private GameObject Head;

    private void Start()
    {
        Head = GameObject.Find("Camera");
    }

    private void Update()
    {
        Vector2 pos = move.GetLastAxis(SteamVR_Input_Sources.LeftHand);
        transform.position += Head.transform.forward * pos.y * MoveSpeed;
        transform.position += Head.transform.right * pos.x * MoveSpeed / 5;
        Vector3 loc = transform.position;
        loc.y = 0;
        transform.position = loc;

        if (left.GetStateDown(SteamVR_Input_Sources.RightHand))
        {
            transform.Rotate(new Vector3(0, -20, 0));
        }

        if (right.GetStateDown(SteamVR_Input_Sources.RightHand))
        {
            transform.Rotate(new Vector3(0, 20, 0));
        }
    }
}

 これでだいぶ直感的に動けるようになりました。

なぜこの記事を書いたか

  • 同じことを解説しているページはあったが、ジョイスティックでの移動をシンプルに実装するという点で優位性があると思った
  • バージョンが細かく分かれており、2.6.1で書いている記事はなかった
  • Indexで書いている記事もなかった

お世話になった記事

https://framesynthesis.jp/tech/unity/htcvive/
https://qiita.com/sakano/items/d87a9b11c23a9bbe166f

8
6
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
6