VR開発メモトップ

Unity+Oculus Rift開発メモ

最終更新日:2017年06月15日

UnityでOculus Rift対応ソフトを開発する方法やTipsをまとめています。

更新履歴

(2017年6月15日)「立って体験するソフトを作るには」にUnity本体のAPIを使う方法を追記、その他リンク等を修正
(2017年4月9日)Unityの対応バージョンについて更新
(2017年1月11日)Unityの対応バージョンについて更新
(2016年12月20日)「VR空間でシーンを編集するには」を追加
(2016年12月8日)Touch関連を「Unity+Oculus Touch開発メモ」に分離

目次


UnityでOculus Rift対応ソフトを作るには

Unityは標準でVRサポートが組み込まれており、Oculus Riftにも対応しています。不具合が起きるときはパッチリリースベータ版プログラムを含め、バージョンを変えて試してみてください。なお、Windows版のUnityはインストール時にフォルダを変更すると複数のバージョンを併用できます。

自作のソフトをOculus Riftで動かすには、Oculusアプリの設定を変更する必要があります。

Oculusアプリを起動して右上の歯車アイコンをクリック、Settingsを選択、左のGeneralを選択してUnknown Sourcesをオンにします。この設定は一度変更するとOculusアカウントに保存されます。

UnityのプロジェクトをOculus Riftに対応させるには、Player SettingsのOther Settingsにある「Virtual Reality Supported」をチェックしてオンにしてください。エディタの再生ボタンを押すか、Standaloneでビルドして実行し、Oculus Riftを被って表示されれば成功です。警告画面でゲームコントローラーのボタンを押すか、画面下のメッセージを2秒間注視するとスタートします。

ビルドして実行する際、Riftの画面がPlease wait …の表示で止まっている場合は、Unityの起動ダイアログでPlayをクリックします(Oculusソフトウェアのウィンドウの下に隠れていることがあります)。

また、Unity公式からVR Samplesというサンプルプロジェクトが提供されています。とりあえずこれをビルドしてみるのがおすすめです。同じくUnity公式のVRのチュートリアルは英語ですが非常に分かりやすい内容になっています。

さらに、Oculus VRのダウンロードページにあるOculus Utilities for Unity 5をインポートすることで、Oculus Rift固有の機能が使えるようになります(「Oculus Utilitiesは何をするの?」を参照)。

動かない/スムーズに動かない

上手く行けば、ビルドしたものがスムーズに動いてヘッドトラッキングもぴったりついてくるはずですが、そうでない場合、何かがおかしいです。

以下のようなことを試してみてください。

エディタ上で再生するとカクつくんだけど

Gameビューの「Maximize on Play」をオンにして再生してみてください。最大化せずに再生すると、インスペクタの表示などが負荷になり、フレームレートが低下します。

ビルドしたアプリが動かないんだけど

exeファイルの出力先フォルダまたはその親フォルダの名前に日本語や全角英数が含まれていると、Riftが認識されないようです。半角英数のみのフォルダで実行してください。

## Windows 10でも大丈夫?

対応しています。Windows 10は64ビット版が必要です。


開発Tips

Virtual Reality Supportedをオンにすると何が起きるの?

ビルドするとOculusのプラグインが出力ファイルに同梱され、Oculus Riftが接続されていると自動的にOculus Riftにも出力するようになります。Render Textureの設定されていないカメラが自動的にステレオレンダリングになり、左右両画面のカリングやシャドウマップの共通化などの最適化が行われます。

また、実行時にカメラのField of ViewがHMDにあわせて変更され、PositionとRotationがトラッキングの動きで上書きされるようになります。このため、スクリプトなどでカメラを動かす場合には、他のオブジェクトの子オブジェクトにする必要があります。

Oculus Riftが接続されていなければ通常通りPCに表示されます。これによって、Oculus Riftと非Oculus Rift両対応のソフトを作ることができます。

Oculus Utilitiesは何をするの?

Oculus VRのダウンロードページにあるOculus Utilities for Unity 5をインポートすると、UnityのVRサポート機能にはない、以下のようなOculus Rift固有の機能を使用できるようになります。

なお、Oculus Utilitiesの機能を使用すると、当然ながらOculus Rift依存のアプリケーションになります。他のヘッドセットへの移植を考慮する場合、できるだけUnity本体の機能のみで作り、依存箇所を何らかの方法で吸収することを考えたほうがいいかもしれません。

位置トラッキングの合わせ方を教えて

まず、シーン内のカメラをプレイヤーの頭の位置(正確には両目の中間)に配置してください。その上で、実行中にちょうどいい場所に立つ、椅子に深く座るなどして、キーなどでトラッキングのリセットをかけます。以下のようなスクリプトを適当なゲームオブジェクトにアタッチして使います。

using UnityEngine;
using UnityEngine.VR;

public class Recenter : MonoBehaviour
{
    void Update()
    {
        // Rキーで位置トラッキングをリセットする
        if (Input.GetKeyDown(KeyCode.R))
        {
            InputTracking.Recenter();
        }
    }
}

Riftが位置トラッキングカメラの視界に入ってさえいれば、位置・向きとも比較的自由にトラッキングされます。

なお、位置トラッキングカメラを動かしたときは、Oculusアプリでリセットする必要があります。右上の歯車>Settings>Devices>右上のConfigure Rift>Configure Riftで目の高さを入力し、「Set Your View in VR」の表示が出たらRiftをかぶって、正面を向いてXboxコントローラーのAボタンを押します。

Sceneビューのカメラアイコンが大きくて位置がよく分からない

SceneビューのバーにあるGizmosをクリックして、3D Gizmosのスライダーを左に動かしてみてください。

立って体験するソフトを作るには

Oculus Utilitiesを使用する方法

Oculus UtilitiesをOculus VRのダウンロードページからダウンロードしてプロジェクトにインポートしてください。

地面をy=0の高さに配置して、OVRCameraRigを(0, 0, 0)に配置し、OVR ManagerコンポーネントのTracking Origin TypeをFloor Levelに変更します(Unityの通常のカメラにOVR Managerコンポーネントをアタッチしてもいいようです)。

これで再生するとVR空間と現実世界の地面の高さが合っているはずですが、合っていない場合は、OculusソフトウェアのDevices > Configure Rift > Reset Sensor Trackingで位置トラッキングカメラのキャリブレーションをやり直します。途中で身長を正確に入力し、立った状態でキャリブレーションする必要があります。ボタンを押したときのヘッドセットの高さと入力した身長をもとに床の高さが決定されます。

Unity本体のAPIを使用する方法

Unity 5.6以降で、VRサポートのAPIで位置トラッキングのモードを変更できます。ルームスケールモード(TrackingSpaceType.RoomScale)と着席モード(TrackingSpaceType.Stationary)が選択でき、Riftではデフォルトは着席モードになっています。

using UnityEngine;
using UnityEngine.VR;

public class VRSetup : MonoBehaviour
{
    void Start()
    {
        // デフォルトはTrackingSpaceType.Stationary
        VRDevice.SetTrackingSpaceType(TrackingSpaceType.RoomScale);
    }
}

スケール(縮尺)の合わせかたを教えて

Riftの左右の映像はUnityのシーン内で左右の目の間隔(デフォルトでは6.4cm)ぶんずらした位置からレンダリングされ、この両眼視差によってVR空間の物体が現実的な大きさに感じられるようになっています。Unityは1ユニット=1メートルになっていますので、特に実写系のコンテンツではこれに従うのが基本です。例えば、身長170cmのキャラクターを出すときは、Unity上で頭頂まで縦1.7になるようにサイズを調整します。

オブジェクトのサイズを調整する際には、エディタ上でCubeオブジェクトを作って適当なスケールを入力して、定規代わりにすると便利です。

また、普段の生活で大きさをよく知っているものをVR空間に出してスケール感の手がかりにするのも良いかと思います。

Unity GUIを使うには?

Canvasを作成しRender ModeをWorld Spaceにして、Scaleを0.01などに設定して小さくしてシーンに配置します。

UIをカメラの向きに追随させて常に同じ位置に表示する場合は、Render ModeをScreen Space - CameraにしてRender Cameraにカメラを割り当て、Plane Distanceに表示する距離(メートル)を設定します。

なお、Oculusのベストプラクティスでは、UIは3D空間の構成要素として作成し、視点から2~3メートル=ユニットの距離に表示することが推奨されています。

UIとのインタラクションについては、Unity公式のVR Samplesに含まれているスクリプトを使用するのが簡単です。使い方や、VRでのUIの考え方については、チュートリアルのInteraction in VRおよびUser Interfaces for VRで解説されています(手抜きですいません。そのうち詳しく……)。

描画設定やアンチエイリアスについて

アンチエイリアスについては、Oculus VR社のvrdaveb氏のコメントによれば、Player SettingsでRendering PathをForwardにして、Quality SettingsのAnti AliasingでMulti Sampling(MSAA)をかけることが推奨されています。Deferredは帯域コストが高く、MSAAが使えないため不利になります。MSAAはイメージエフェクトのアンチエイリアス(FXAA)よりも軽量で、ポリゴンのエッジが綺麗です。ただし、HDRレンダリングをする場合はMSAAが使えないため、FXAAを使うことになります。

同じくPlayer SettingsのColor SpaceをGammaではなくLinearにすることが推奨されています。

レンダリング解像度を変更するには?

GPUの描画負荷は、描画するピクセル数と、ピクセルあたりのシェーダの複雑さに比例することが多いです。パフォーマンスが出ない場合、VRSettings.renderScaleでレンダリング解像度を下げると効果がある場合があります。

UnityEngine.VR.VRSettings.renderScale = 0.5f; // デフォルトは1.0f

また、Oculus Utilitiesを使うと、GPUの使用率が高くなるとフレーム落ちしないように自動的に解像度を下げるAdaptive Resolutionという機能を使用できます。OVRCameraRigのOVR ManagerにあるEnable Adaptive Resolutionをオンにしてください。

Oculus Riftの位置・向きを取得するには?

Oculus Riftの位置・向きによってカメラのtransformが変化しますので、これを参照できます。

もしくは、InputTracking.GetLocalPosition/GetLocalRotationでカメラオブジェクトを基点にしたローカル座標と向きが取得できます。

using UnityEngine.VR;
...
Vector3 position = InputTracking.GetLocalPosition(VRNode.CenterEye);
Quaternion rotation = InputTracking.GetLocalRotation(VRNode.CenterEye);

VRNode.LeftEye/RightEye/CenterEye/Headでそれぞれ左右の目と、目の中間、頭部の位置・向きが取得できます。CenterEyeとHeadは同じ値が戻ってくるようです。

Oculus Riftの接続チェックをするには?

Riftが接続されていれば、VRDevice.isPresentがtrueになります。

using UnityEngine.VR;
...
if (VRDevice.isPresent) { /* Riftあり */ }

接続しているデバイスの種類を知るには?

VRDevice.modelまたはVRSettings.loadedDeviceNameを使用します。

using UnityEngine.VR;
...
Debug.Log("VRDevice.model = " + VRDevice.model);
Debug.Log("VRSettings.loadedDeviceName = " + VRSettings.loadedDeviceName);

このような出力が得られます。

VRDevice.model = Oculus Rift CV1
VRSettings.loadedDeviceName = Oculus

PCの画面に別視点の映像を表示するには?

カメラをシーンに追加し、Target Eyeを「None (Main Display)」に設定してください。また、どちらかのカメラから余分なAudio Listenerを削除してください。ビルドして実行すると別視点の画面がPC側に表示されます。

PC側のカメラのDepthの数値をRift側のカメラより大きくしておく必要があります。もしくは、VRSettings.showDeviceViewでRift側のカメラのミラー表示を無効にしてください(こちらのほうがより軽量なのではと思います)。

using UnityEngine;

public class HideRiftView : MonoBehaviour
{
    void Start()
    {
        UnityEngine.VR.VRSettings.showDeviceView = false;
    }
}

なお当然ですが、一画面余分にレンダリングしますので、そのぶん負荷が増えます。フレーム落ちする場合は、起動ダイアログの解像度設定を下げてみてください。

別のPCでプログラムをもう1つ動かして、ネットゲームの要領で同期表示することを検討してもいいかもしれません。

シーンにカメラを複数設置して同時描画できる?

通常のプロジェクトと同じようにカメラを複数使用してレイヤー表示できます。後から描画する方のカメラのClear FlagsをDepth OnlyもしくはDon’t Clearに、Depthを1以上に変更してください。また、余分なAudio Listenerを削除してください。

Oculus Utilitiesを使用している場合、OVRCameraRigが複数あると警告が出ます。Unityの通常のカメラを追加してください。

キャラクターのスケールを変更したい

既存のプロジェクトが1ユニット=1メートルになっていない場合や、巨人の視界などを表現したいというような場合があります。

カメラを別のオブジェクトの子にして、親オブジェクトのScaleを変更すれば実現できます。カメラ自身のScaleを変更しても反応しないので注意です。

サウンドに関する注意

ヘッドホンとスピーカーでは音声の定位が異なります。ヘッドホンは頭を動かすと一緒に回りますが、スピーカーは回りません。スピーカーで音声を出力する場合は、カメラからAudio Listenerを削除して別のオブジェクトにアタッチする必要があります。

Xbox Oneコントローラーの入力を取るには?

Unity本体で取得する場合、Input Managerにおけるジョイスティックの軸とボタンのマッピングは以下のようになっています。

Axis/Button
X axis 左アナログスティック X軸(左-1~右1)
Y axis 左アナログスティック Y軸(上-1~下1)
4th axis 右アナログスティック X軸(左-1~右1)
5th axis 右アナログスティック Y軸(上-1~下1)
7th axis 方向キー X軸(左-1、右1)
8th axis 方向キー Y軸(下-1、上1)※アナログスティックと逆
3rd / 9th axis LT(リリース-1~最大1)
6th / 10th axis RT(リリース-1~最大1)
joystick button 0 Aボタン
joystick button 1 Bボタン
joystick button 2 Xボタン
joystick button 3 Yボタン
joystick button 4 LB
joystick button 5 RB
joystick button 6 ビューボタン(中央左のボタン)
joystick button 7 メニューボタン(中央右のボタン)
joystick button 8 左アナログスティック押し込み
joystick button 9 右アナログスティック押し込み
joystick button 10 Xboxボタン

または、Oculus UtilitiesのOVRInputで取得します。

Oculus Remoteの入力を取るには?

Unity 5.4.1以降でジョイスティック入力として取得できます。Input Managerにおける軸とボタンのマッピングは以下のようになっています。Xbox Oneコントローラーの方向キーおよびA/Bボタンと同一になっています。

Axis/Button
7th axis 方向キー X軸(左-1、右1)
8th axis 方向キー Y軸(下-1、上1)
joystick button 0 Selectボタン
joystick button 1 Backボタン

Oculusボタンと2つのボリュームボタンにはアクセスできません。

また、Input.GetJoystickNames()で取得できる文字列の配列に”Oculus Remote”が入っています。

Oculus UtilitiesのOVRInputでも取得できます。

Oculus Homeに戻るには?

Application.Quit()で終了します。または、Universal MenuでいつでもExit to Homeできます。終了時にOnApplicationQuit()が呼ばれますので、ここでデータの保存処理などを行います。

Oculus Riftをかぶっていないときも動作が止まらないようにするには?

Oculus Riftには、ヘッドセット内の中央上に近接センサーがあり、ヘッドセットをかぶっていないときには表示が消えるようになっています。これは有機ELパネルの焼き付きを防ぐためで、現状ソフトウェアで無効にすることはできません。

展示等でアプリケーションが動作しつづけるようにしたい場合は、一つの方法として、この近接センサーにテープか何かを貼って騙すことができます。

また、もう一つの方法として、PC側の画面だけは動くようにすることができます。Player SettingsのRun In Backgroundをチェックして、Target Eyeを「None (Main Display)」にしたPC側カメラをシーンに配置します。PC側カメラのDepthはヘッドセット側カメラのDepthよりも小さくしてください。こちらの方法のほうが、待機中にデモ画面を流したりしやすいかもしれません。

なお、このままだとPC側カメラで常にレンダリングするためそのぶんの描画負荷がかかってしまいますが、Oculus UtilitiesのOVRCameraRigを使用して、OVRManagerコンポーネントのisUserPresentでヘッドセットをかぶっているかどうかを取得できますので、これを利用して、必要ないときにPC側カメラを無効にすることができます。

位置トラッキングカメラの位置を取得するには

Oculus Utilitiesが必要ですので、Oculus VRのダウンロードページからダウンロードしてプロジェクトにインポートしてください。

OVRManager.tracker.countで接続している位置トラッキングカメラの数が、OVRManager.tracker.GetPose({番号})で各カメラのpositionとorientationが取得できます。

unsupported graphics APIと怒られる

VRサポートを有効にしても、

[Compositor] ERROR: Cannot start with unsupported graphics API.
Bad config or LibOVR not found. VR disabled.

と表示されてVRモードにならない場合、Player SettingsのGraphics APIs for WindowsでDirect3D9が使用されている可能性があります。すぐ上のAutomatic Graphics APIをチェックしDirect3D11が使用されるようにして、Unityを再起動してください。

VR空間でシーンを編集するには

UnityからEditorVRというVR空間で直接シーンを編集できる実験ビルドが提供されています。「Unity EditorVRについて」ページを参照してください。


不具合など

個人的に遭遇・把握している不具合を載せます。


Oculus Touchについて

Unity+Oculus Touch開発メモ」に移動しましたので、そちらを参照してください。


番外編

Oculus Platform SDKで、ストア向けアプリにおいて、リーダーボード、マルチプレイヤーマッチメイキング、P2Pネットワーキングなどがサポートされています。Oculus SDK for WindowsのPlatformSDK¥UnityにUnity用のパッケージが入っています。

製品版のOculusソフトウェア向けにビルドするとOculus Rift DK2の画面が旧Oculus Runtimeと比べ明るくなりますが、仕様とのことです。輝度を上げてガンマを正確にしたとのことです。

Leap MotionのOculus Rift製品版についてのFAQが公開されています。


参考リンク

書いた人:こりん(@k0rin
リンク切れや間違いなどございましたらメールやTwitterでご指摘ください。
VR開発メモトップ RSS