UnityでOculus Integrationを使わずにOculus TouchやHMDのパラメータを取得する方法(for Oculus Quest)


最初に

Oculus Questアプリの開発においてはOculus Integrationを使うのが正しい手法だとは思いますが、マイノリティな方法として表に出ていない気がしたのでメモしておきます。メリットとしては入力系の処理を通常のUnityアプリと同じ肌感覚で実装でき、Unityのバージョンアップ時にアセット側のアップデートを待たなくて良い点があります。デメリットとしてはGrabやMoveやuGuiの入力処理など、ライブラリに依存している部分の処理を自前で実装しなくてはいけない点です。

ビルド環境については先人の知恵を参考にしましょう。

Unity+Oculus Quest 開発メモ - フレームシンセシス

Oculus Quest に Unity で開発したアプリをいれる方法(Mac/Win) - Qiita


開発環境

Unity 2019.1.5f1 Personal


Oculus Touchの入力をInputManagerで設定する

参考 : OpenVR コントローラーの入力

Edit > Project Settings > Inputから設定していきます。サンプルについては以下のスクリーンショットを。

setting_xy.PNG

setting_xy2.PNG

setting_12.PNG

setting_r12.PNG

setting_1617.PNG

setting_leftindex.PNG

setting_rightindex.PNG

setting_89.PNG

InputManagerの設定後、以下のスクリプトをGameObjectにアタッチすると、入力値をチェックできます。


TouchChecker.cs

using UnityEngine;

public class TouchChecker : MonoBehaviour
{
void Update()
{
if(Input.GetAxis("Horizontal") != 0){
Debug.Log("Horizontal:" + Input.GetAxis("Horizontal"));
}

if(Input.GetAxis("Horizontal2") != 0){
Debug.Log("Horizontal2:" + Input.GetAxis("Horizontal2"));
}

if(Input.GetAxis("Vertical") != 0){
Debug.Log("Vertical:" + Input.GetAxis("Vertical"));
}

if(Input.GetAxis("Vertical2") != 0){
Debug.Log("Vertical2:" + Input.GetAxis("Vertical2"));
}

if(Input.GetButtonDown("VR_Left_Button1")){
Debug.Log("l1");
}

if(Input.GetButtonDown("VR_Left_Button2")){
Debug.Log("l2");
}

if(Input.GetButtonDown("VR_Right_Button1")){
Debug.Log("r1");
}

if(Input.GetButtonDown("VR_Right_Button2")){
Debug.Log("r2");
}

if(Input.GetButtonDown("VR_Left_Start")){
Debug.Log("lStart");
}

if(Input.GetButtonDown("VR_Left_Button8")){
Debug.Log("l push");
}

if(Input.GetButtonDown("VR_Right_Button9")){
Debug.Log("r push");
}

if(Input.GetAxis("VR_Left_Index") > 0){
Debug.Log("VR_Left_Index:" + Input.GetAxis("VR_Left_Index"));
}

if(Input.GetAxis("VR_Left_Hand") > 0){
Debug.Log("VR_Left_Hand:" + Input.GetAxis("VR_Left_Hand"));
}

if(Input.GetAxis("VR_Right_Index") > 0){
Debug.Log("VR_Right_Index:" + Input.GetAxis("VR_Right_Index"));
}

if(Input.GetAxis("VR_Right_Hand") > 0){
Debug.Log("VR_Right_Hand:" + Input.GetAxis("VR_Right_Hand"));
}
}
}



トラッキングポジションの取得

主観ですが、RoomScaleよりStationaryの方が開発しやすいです。

RoomScaleが前提のアプリでも、Stationaryで作っています。闇ですね。

以下のスクリプトをGameObjectにアタッチすると、トラッキングポジションをチェックできます。


TrackingSample.cs

using UnityEngine;

using UnityEngine.XR;

public class TrackingSample : MonoBehaviour
{
void Start()
{
XRDevice.SetTrackingSpaceType(TrackingSpaceType.Stationary);
////RoomScaleの場合
// XRDevice.SetTrackingSpaceType(TrackingSpaceType.RoomScale);
}

void Update()
{
Debug.Log("LeftHand_Position : " + InputTracking.GetLocalPosition(XRNode.LeftHand));
Debug.Log("RightHand_Position : " + InputTracking.GetLocalPosition(XRNode.RightHand));
Debug.Log("HMD_Position : " + InputTracking.GetLocalPosition(XRNode.CenterEye));
Debug.Log("LeftHand_Rotation : " + InputTracking.GetLocalRotation(XRNode.LeftHand));
Debug.Log("RightHand_Rotation : " + InputTracking.GetLocalRotation(XRNode.RightHand));
Debug.Log("HMD_Rotation : " + InputTracking.GetLocalRotation(XRNode.CenterEye));
}
}



カメラについて

camera.PNG

空のGameObjectと親子関係にして、親のObjectを動かすのがベストだと思います。


Oculus Questで使えなかった機能

InputTracking.Recenter(); → OculusButtonの長押しで代用可能なので、そこまで重要ではない。

Button.Start(Unity Button ID : 7) → Oculus Quest上で反応無し。Oculus Riftでも使用不可能(Riftの場合はSteamVR側にBINDされているのが原因?)。


最後に

Oculus Integrationに依存したくない方、全て自力で実装したい場合について、この方法は有用なんじゃないかと思います。Oculus Rift向けに作成したアプリについては、ステレオパスでビルドターゲットを変更するだけで簡単に動作しました。パフォーマンスは当然微妙でしたが。


参考リンク

XR - Unity マニュアル

102 2 レーザーコントローラー · yumemi-inc/vr-studies Wiki

Unity標準のVR機能(UnityEngine.XR)メモ - フレームシンセシス