(:3[kanのメモ帳]

個人ゲーム開発者kan.kikuchiのメモ的技術ブログ。月木更新でUnity関連がメイン。

Oculus Integrationを使ってOculus Goでの移動やコントローラの表示&同期を実装【Unity】【VR】【アセット】【Oculus Go】


このエントリーをはてなブックマークに追加

この記事でのバージョン
Unity 2017.4.4f1


はじめに

前にUnity製アプリをOculus Goで動かすという記事と、



Oculus Goの主要な入力をUnityで受け取るという記事を書きました。



これでUnity製アプリをOculus Goで動かせる上に

入力を受け取れるようになったので、後は動き回るだけですね!


という事で今回は、VR空間上で移動したり、

コントローラの表示&同期をしたりしてみよう!という感じの記事です!


もちろん今回も楽にOculus Go周りの実装が出来るアセット、Oculus Integrationを使います。



なお、本記事に出てくる家のアセットは以下のものを使っています。





OVRCameraRig

まずはコントローラの表示&同期からです。

と言ってもOculus Integrationを使えば、超簡単で

VR/PrefabsにあるOVRCameraRigをシーンに配置し、配置したOVRCameraRigの子にある

LeftHandAnchorとRightHandAnchorの下にさらにTrackedRemoteを配置するだけ。


f:id:kan_kikuchi:20180612150251j:plain


あとは配置したPrefabに付いてるスクリプトが

各アンカーのTransform更新(RightHandAnchorなら常に右手当たりの位置に)や、

左右のコントローラの切り替え、GearVRとOculus Goのコントローラの切り替え、

コントローラの同期等、いい感じにやってくれます。


f:id:kan_kikuchi:20180613094826g:plain


なお、OVRCameraRig(の子)にはカメラも付いているので、

元から配置されているカメラ(Main Cameraとか)は消しましょう。


OVRPlayerController

次にVR空間上での移動です。

これもOVRPlayerControllerといういかにもなPrefabで行けるかと思いましたが、


f:id:kan_kikuchi:20180612152208j:plain


キーボードで操作するように作られているようで、Oculus Goでは使えませんでした。

キーボードの入力部分を書き換えれば一応使えますが、そもそもボタンが足りないので、

OVRPlayerControllerの事は忘れて、よくある移動方法とそのプログラムを2パターンほど紹介します!


なお、プログラムの詳細な説明は省きますが、

RequireComponentという属性Resetというメソッド

気になった方は以下の記事が参考になるかと思います。




また、先程紹介したOVRCameraRigで使うためのもので、

それ以外のオブジェクトに付けても動作しません。(_centerEyeAnchorが取得出来ないため)


Transfomの座標を直接操作

おそらく最も簡単な移動は、座標を直接操作する方法です。

実際のプログラムは以下のような感じです。

using UnityEngine;

/// <summary>
/// Transfomの座標を直接操作して移動するクラス
/// </summary>
public class TransfomMover : MonoBehaviour {

  //VR上で目の中心(見ている方向)を確認する用のアンカー
  [SerializeField]
  private Transform _centerEyeAnchor = null;

  //移動速度の係数
  [SerializeField]
  private float _moveSpeed = 2;

  //=================================================================================
  //初期化
  //=================================================================================

  //コンポーネントがAddされた時に実行される
  private void Reset() {
    //中心のアンカー取得
    _centerEyeAnchor = transform.Find("TrackingSpace/CenterEyeAnchor");
  }

  //=================================================================================
  //更新
  //=================================================================================

  private void Update () {
    //タッチパッドを触っている所の座標(-1 ~ 1)取得
    Vector2 primaryTouchpad = OVRInput.Get(OVRInput.Axis2D.PrimaryTouchpad);

    //Yの+の方向のMaxが0.5ぐらい(デバイスの不具合かも?)なので増やす
    if(primaryTouchpad.y > 0){
      primaryTouchpad.y *= 2;
    }

    //向いてる方向、タッチパッドを触ってる場所から移動距離計算
    Vector3 distance = _centerEyeAnchor.rotation * new Vector3(primaryTouchpad.x, 0, primaryTouchpad.y);

    //上向いてる時に上にいっちゃうので上下方向の速度0に
    distance.y = 0;

    //上下方向の速度を減らした分を左右に振るために正規化
    float speedMagnitude = _moveSpeed * primaryTouchpad.magnitude;//速度の大きさ
    distance = distance.normalized * speedMagnitude;

    //座標を直接操作して移動
    transform.position += distance * _moveSpeed * Time.deltaTime;
  }

}


このTransfomMoverをOVRCameraRigにAddすると、

自動でCenterEyeAnchorがアタッチされ、


f:id:kan_kikuchi:20180613091722j:plain


コントローラの丸いタッチ部分を触る事で移動出来るようになります。

上の方を触れば前へ、右の方を触れば右と言った具合です。


また、MoveSpeedで移動速度を調整する事も可能です。


f:id:kan_kikuchi:20180613095202g:plain


ただし、この方法ではコライダーを付けても当たり判定を実装する事は出来ません。


Rigidbodyの速度を操作

次に紹介するのはRigidbodyを使った移動方法で、当たり判定が欲しい時に使えます。

実際のプログラムは以下のような感じです。

using UnityEngine;

/// <summary>
/// Rigidbodyの速度を操作して移動するクラス
/// </summary>
[RequireComponent(typeof(Rigidbody))]//Rigidbody必須(Add時になければ自動で追加される)
public class RigidbodyMover : MonoBehaviour {

  [SerializeField]
  private Rigidbody _rigidbody = null;

  //VR上で目の中心(見ている方向)を確認する用のアンカー
  [SerializeField]
  private Transform _centerEyeAnchor = null;

  //移動速度の係数
  [SerializeField]
  private float _moveSpeed = 3;

  //現在の移動速度
  private Vector3 _currentVelocity = Vector3.zero;
	
  //=================================================================================
  //初期化
  //=================================================================================

  //コンポーネントがAddされた時に実行される
  private void Reset() {
    //中心のアンカー取得
    _centerEyeAnchor = transform.Find("TrackingSpace/CenterEyeAnchor");

    //Rigidbody取得、初期設定
    _rigidbody = gameObject.GetComponent<Rigidbody>();
    _rigidbody.useGravity     = false;
    _rigidbody.freezeRotation = true;
  }

  //=================================================================================
  //更新
  //=================================================================================

  //入力はUpdateで確認
  private void Update () {
    //タッチパッドを触っている所の座標(-1 ~ 1)取得
    Vector2 primaryTouchpad = OVRInput.Get(OVRInput.Axis2D.PrimaryTouchpad);

    //Yの+の方向のMaxが0.5ぐらい(デバイスの不具合かも?)なので増やす
    if(primaryTouchpad.y > 0){
      primaryTouchpad.y *= 2;
    }

    //向いてる方向、タッチパッドを触ってる場所から速度計算
    _currentVelocity = _centerEyeAnchor.rotation * new Vector3(primaryTouchpad.x, 0, primaryTouchpad.y);

    //上向いてる時に上にいっちゃうので上下方向の速度0に
    _currentVelocity.y = 0;

    //上下方向の速度を減らした分を左右に振るために正規化
    float speedMagnitude  = _moveSpeed * primaryTouchpad.magnitude;//速度の大きさ
    _currentVelocity      = _currentVelocity.normalized * speedMagnitude;
  }

  //物理演算関係(今回は速度)はFixedUpdateで設定
  private void FixedUpdate() {
    _rigidbody.velocity = _currentVelocity;
  }

}


このRigidbodyMoverをOVRCameraRigにAddすると、

自動でRigidbodyがAdd&設定&アタッチ、CenterEyeAnchorもアタッチされ、


f:id:kan_kikuchi:20180613094350g:plain


先程と同様、コントローラの丸いタッチ部分を触る事で移動出来るようになります。

なお、MoveSpeedで移動速度を調整出来るのも同じです。


f:id:kan_kikuchi:20180613095344g:plain


この方法ならコライダーを付ければ当たり判定を実装するが出来ます。

(上記のgifでもカメラとベットにコライダーが付いてるため進めなくなっている)


f:id:kan_kikuchi:20180613095556j:plain