【Unity】【SteamVR】コントローラの位置、回転について備忘録

最近、VIVEというHMDを借りる機会がありました。

VIVEには、最初からトラッカー機能が付いたコントローラがついてきます。
今回は、このコントローラをトラッカーとして使う場合に必要になってくる、位置と回転について分かった事を記載していきます。

コントローラの位置情報取得方法

コントローラの制御は、SteamVR_TrackedControllerを使います。

今回は、下記のように、コントローラーの位置情報がそれぞれ左右のUIに入力されるようなアプリの作り方です。
f:id:nakahashi_h:20180906041120p:plain

まず、コントローラに追加するスクリプトを作成します。
ViveControllerTracking.csというファイルを作り、下記のスクリプトを追加します。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ViveControllerTracking  : MonoBehaviour {
    
  private PrimitiveType currentPrimitiveType = PrimitiveType.Sphere;
  public RotateTextController rotateText;
  public PostionTextController positionText;

  private void OnEnable()
  {
      // コントローラのトラッキング制御を取得
      trackedController = gameObject.GetComponent<SteamVR_TrackedController>();
      if (trackedController == null)
      {
          // トラッキング制御を所得でいなかった場合は、SteamVR_TrackedControllerを追加する
          trackedController = gameObject.AddComponent<SteamVR_TrackedController>();
      }
  }

  void Update () {
      // コントローラーのポジション情報取得
      // サンプル画像の位置(positionToString)に取得した値を代入します
      positionText.GetComponent<PostionTextController>().positionToString
         = trackedController.transform.position.ToString();

      // コントローラーの回転取得
      // サンプル画像の回転(rotationToStoring)に取得した値を代入します
      rotateText.GetComponent<RotateTextController>().rotationToStoring
          = trackedController.transform.rotation.ToString();
  }
}

値の取得は、普通のオブジェクトと同じように次の方法で取得します。

  • 位置の場合は、transform.position
  • 回転の場合は、transform.rotation

テキスト側の設定

UIに描画させるので、表示するためのテキストを用意します。
UI->textで、2つオブジェクトを作り、それぞれ、適当な名前を付けます。

作成したオブジェクトに、それぞれ、次のスクリプトを追加します。

回転のテキストに追加するスクリプト

RotateTextController.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class RotateTextController : MonoBehaviour {

    public string rotationToStoring;                   // 回転で表示する文字情報
    private string template = "回転:";                // 操作のテンプレート名

    // Use this for initialization
    void Start()
    {
    }

    // Update is called once per frame
    void Update()
    {
        this.GetComponent<Text>().text = template + rotationToStoring;
    }

}

位置のテキストに追加するスクリプト

PostionTextController.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class PostionTextController : MonoBehaviour {

    public string positionToString;         // 表示するポジションの文字情報
    private string template = "位置:";     // 操作のテンプレート名

    // Use this for initialization
    void Start()
    {
    }

    // Update is called once per frame
    void Update()
    {
        this.GetComponent<Text>().text = template + positionToString;
    }

}

コントロールにC#コンポーネントを追加する

VIVEのアプリケーションを作る時に、Projectの下記からCameraRigのプレファブをHierarchyに追加したと思います

Assets->SteamVR->Prefabs->[CameraRig]

コントローラー、およびHMDは、HierarchyのCameraLigの中に入っています。   f:id:nakahashi_h:20180906034126p:plain

Controller(left)、Controller(Right)に先ほど作ったViveControllerTracking.csを追加します。
その際に、「Rotate Text」と、「PositionText」各UI用のtextも一緒に指定します。

f:id:nakahashi_h:20180906042609p:plain

VIVEから取得する値について

回転情報について

Unityにおける回転表示方法の概念

Unityは回転の表し方が二種類あって、

  • Vector3型で表す、オイラー角
  • Quaternirion型で表す、クォータニオン

docs.unity3d.com

この記事では詳細に記載しませんが、簡単に言うと、角度の表し方が違います。
例えば、xyz方向にそれぞれ、45度傾けた状態をそれぞれの型で表すと次のようになります。

オイラー角
45, 45, 45;
クォータニオン
0.5, 0.2, 0.2, 0.8

VIVEの場合

回転はクォータニオンで取得されます。
実際に、取得してみると次のような結果がわかりました。

正面に配置

f:id:nakahashi_h:20180906040820j:plain

(0, 0, 0, 1.0)
反対向きにして配置

f:id:nakahashi_h:20180906040837j:plain

(-1, 0, 0, 0)
右向きにして配置

f:id:nakahashi_h:20180906040852j:plain

(-0.7, 0, -0.7, 0)

位置情報

CameraRigを設置した位置を0地点としたlocalscaleで表示されます。

Sceneウィンドウを見ると、水色で囲まれた部分がCameraRigの範囲になります。 f:id:nakahashi_h:20180906041457p:plain

位置の単位について

公式では次のように書かれています。

Transform のスケールはあなたのモデリングアプリケーションでのメッシュの大きさとユニティでそのメッシュの大きさとの違いを決定します。
ユニティ上でのメッシュサイズは( Transform のスケール)は、特に物理シミュレーションにとって大変重要です。 デフォルトでは、物理エンジンはワールド空間上で 1 単位を 1 メートルに対応することを前提としています

docs.unity3d.com

大きさ(Scale)の話ではありますが、ScaleとPositionは同じサイズ感ですし、
下記と説明される方もいらっしゃるので、1mという認識で良いかと思います。

teratail.com

参考URL

answers.unity.com stackoverflow.com unity3d.college