VR開発メモトップ

Unity+Oculus Rift開発メモ

最終更新日:2016年07月25日

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

更新履歴

(2016年7月25日)Unityのフォーラムのリンクを修正
(2016年7月12日)Oculus Utilitiesのリンクを変更
(2016年7月7日)Unityのフォーラムのリンクを変更
(2016年6月23日)「Xbox Oneコントローラーの入力を取るには?」を作成
(2016年6月21日)「Oculus Remoteの入力を取るには?」を作成

目次


Oculus Riftについて

Oculus Riftって何?

Oculus Rift(オキュラス・リフト)は、Oculus VR社から販売されているバーチャルリアリティ用ヘッドセットです。比較的広視野な立体視が可能で、かつ、頭を動かして周囲を見回すことができるため、CGの世界に本当に入り込んだような体験ができるのが特徴です。適切に調整すれば、空間内の物体が現実と同じサイズ・同じ場所に見えて、手を伸ばせば触れそうに感じられます。  

Kickstarterでの資金調達ののち、二世代の開発者用キット(DK1、DK2)が販売されていましたが、2016年1月より製品版の予約が公式サイトで開始され、3月末から順次発送が行われています。今注文すると8月以降の発送になるようです。価格は税・送料込みで94600円になっています。製品版でも開発が可能です。

Oculusはラテン語由来で目の意味です。Riftは裂け目で、現実とバーチャル空間の裂け目というようなニュアンスがあるようです。

どういう仕組みなの?

ヘッドセットの中に1080×1200×2枚の有機ELディスプレイパネルがあり、PCでレンダリングした左右両眼の画像を樽型に圧縮したものが表示されます。これをレンズを通して見ることで、パネルのサイズよりも広い視野角(約90~110度)の立体視ができるようになっています。

また、内蔵の各種センサーと外部に設置する位置トラッキングカメラにより頭の向きと位置が取得され、レンダリング時の視点の位置に反映されます。位置トラッキングカメラは赤外線カメラで、ヘッドセットの外装に埋め込まれた不可視の赤外線LED群から位置を推定しています。

PCからヘッドセットへはHDMIで映像を出力します。OSには通常のディスプレイとしては認識されず、GPUドライバから映像が直接出力されます。また、トラッキングデータの取得のためヘッドセットと位置トラッキングカメラをそれぞれUSB 3.0で接続します。

まとめると、PCとの接続は、ヘッドセットのHDMI端子×1とUSB 3.0端子×1および位置トラッキングカメラのUSB 3.0端子×1になります。

一般的なPCやスマートフォンでは、キーボードやタッチ等の入力からディスプレイの表示が更新されるまで50~100ミリ秒ほどのタイムラグがあるのですが、Oculus Riftでは頭の動きからパネルの画素が変化するまでの遅延(motion-to-photonと言っています)が20ミリ秒程度と非常に高速です。ディスプレイのリフレッシュレートが90Hzと通常より高くなっているほか、レンダリング後の各フレームを最新のトラッキング情報に合わせて補正するタイムワープ等、視界を頭の動きと一致させるためのさまざまな工夫が行われています。

問題点はないの?

大きな問題として、VR酔いという乗り物酔いと同じような症状がしばしば発生します。酔いを引き起こす最大の原因は、頭や身体の動きと目で見ている光景のずれ(感覚の不一致)だとされています。Oculus Riftではずれを抑えるさまざまな工夫によってVR酔いをかなり低減できていますが、PCのセットアップや、ソフトの作り方が重要になります。

特にフレームレートの確保が必須で、左右両画面を常時最大フレームレート(90fps)で描画するために高性能なゲーミングPCが必要です。2016年現在では、ハイエンドクラスのGeForceやRadeonが必要になります。詳しくは「Oculus Rift/HTC Vive用PCの選びかた」を参照してください。

また、フレームレートが確保されていても、視点を通常の3Dゲームのように不用意に動かすと酔うため、酔いにくい動かし方をする制作上のノウハウが必要になります。

あと、視野はかなり広いのですが、十分に広いとは言えないかもしれません。現実世界でゴーグルを装着しているような感じです。解像度も広い視野を覆うのに十分ではなく、シーンによってはジャギーが目立つほか、ピクセルの境界で若干網目模様が見えます(網戸効果=screen door effect)。

また、多少重かったり、暑いと汗でレンズが曇ったりします。また、大きいメガネや幅広のメガネが入りません。

他には、必然的に、ヘッドセットを装着すると手元のキーボードやマウス、ゲームコントローラーなどが見えません。周囲が見えないため安全面の問題も生じます。また、VR空間内では自分の手が見えなかったり、身体を動かすと物体をすり抜けてしまったりします。こうした制約をコンテンツや運用でどうカバーするかが鍵になりそうです。 

メガネをかけていても大丈夫?

大きいメガネや幅広のメガネは入りません。小さめのメガネなら入るので、メガネを買い換えるか、コンタクトレンズをすることになるかと思います。実機で一度メガネが入るか確認してみることをおすすめします。なお、開発キットのDK1とDK2では近視用の数種類の交換レンズが付属していましたが、製品版ではレンズの交換はなくなっています。

Oculus VRのサポートページにヘッドセットに入るメガネのサイズは?という項目がありますが、幅14.2cm以下、高さ5cm以下となっています。形状にもよりますが、実際これくらいの数字のようです。

ちなみに、PlayStation VRはメガネが入りやすいです。また、Gear VRもメガネが入りやすいほか、上部ダイヤルで視力にあわせて度を調整できるようになっています。HTC Viveは外周スポンジにメガネのツルのための切れ込みが入っていて、PlayStation VRやGear VRほどではありませんが、Oculus Riftよりも若干余裕があります。

どうすればUnityで使えるの?

Unityは標準でOculus Riftをサポートしています。無料版で大丈夫です。基本的には、「Virtual Reality Supported」の設定をオンにするだけで使用できます。

ただし現状やや癖がありますので、適宜最新情報を追う必要があります。

その他Oculus Rift製品版の特徴について


PC環境について

Oculus Rift用ソフトを開発するには、高性能なGPUを搭載したWindows PCが必要です。詳しくは、「Oculus Rift/HTC Vive用PCの選びかた」を参照してください。


セットアップ編

セットアップするには

まず、ビデオカードのドライバをOculusソフトウェア対応の新しいバージョンに更新します。NVIDIAの場合、GeForce Experienceで「更新プログラムの確認」をして、ドライババージョン364.72以降をインストールします。RadeonはCrimson Edition 16.3.2以降で対応しているとのことです。Oculus VRのサポートページにドライバの案内があります。

Oculus Rift Setupからセットアップツールをダウンロードして実行します。なお、McAfeeなどのアンチウイルスソフトが有効になっているとインストールできないことがあるようです。

デフォルトではストアで購入したアプリは全部Cドライブに保存されます。数十GBあるゲームもあるので、Cドライブの空き容量がない場合はドライブを変更してください(あとで変更できません。アンインストールして再セットアップする必要があります)。

途中でOculusのアカウントがない場合は作成します。

Oculus Rift、Oculus Remote、Xbox Oneコントローラなどの接続設定が出てきます。DK2だとセンサーの警告が出ますが、スキップすれば使用できます。後からOculusソフトウェアでデバイスを追加することができます。

Oculusソフトウェアを実行するとストアのウィンドウが開きます。同時に、Rift側にOculus Homeが起動し、Rift単独でアプリの購入や実行ができます。

Windows 10でも大丈夫?

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

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

Unityは標準でVRサポートが組み込まれており、Oculus Riftにも対応しています。Oculus VRがUnityの推奨バージョンを公開しています。2016年7月2日現在、パッチリリースのUnity 5.3.5p6およびベータリリースの5.4.0b24が推奨バージョンのようです。

自作のアプリケーションをOculus Riftで動かしたり、Oculus Store以外から入手したアプリ(いわゆる野良アプリ)を動かすには、Oculusソフトウェアの設定を変更する必要があります。

Oculusソフトウェアを起動して右上の歯車アイコンをクリック、Settingsを選択、左のGeneralを選択してUnknown Sourcesをオンにします。

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をオンにしておくと、いくらかカクつきが減るかもしれません。

「HEALTH & SAFETY WARNING」の警告メッセージはなくせないの?

製品版のOculusソフトウェアでは消せないようです。ただ、起動して一度消すと再表示されなくなるようですので、あまり邪魔になることはないかもしれません。


開発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 RKeyToRecenter : 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のスライダーを左に動かしてみてください。

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

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 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.family/modelを使用します。

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

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

VRDevice.family = oculus
VRDevice.model = Oculus Rift DK2

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本体では、ベータリリースのUnity 5.4.0b22以降でジョイスティック入力として取得できます。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()が呼ばれますので、ここでデータの保存処理などを行います。

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を再起動してください。


不具合など

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


Oculus Touchについて

Oculus VRは、Oculus Riftとは別に、Oculus Touchという両手に握って操作する入力コントローラを2016年後半に発売予定とのことです。

Oculus Touchはヘッドセット同様、主に外周リング部に埋め込まれた赤外線LEDと位置トラッキングカメラでトラッキングされます。精度の向上と、手や身体でLEDが隠れて位置をロストする問題の軽減のために、少なくとも2つ(“at least two”)の位置トラッキングカメラを使用することになっており、Oculus Touchを購入するともう1つの位置トラッキングカメラがついてくるようです。カメラの配置は比較的自由なようです。

Oculus TouchのAPIはOculus Utilitiesに含まれています。公開されているドキュメント(Oculus Touch ControllersOVRInput)から、以下のような仕様が伺えます。

また、Oculus Touchの位置はOVRCameraRigの子のTransformとして読めるほか、OVRInput.GetLocalControllerPosition/GetLocalControllerRotationで取得できるようです。

Oculus Touchとの無線通信についてはOculus Rift(ヘッドセット)に受信機が入っており、展示でたくさん並べて使用しても電波干渉の心配はないとのことです。

ちなみに、Unreal EngineではMotion ControllerコンポーネントでOculus Touchにアクセスできるようです。


番外編

Oculus Riftアプリケーションの配布方法は?

普通に自分のウェブサイトで公開するほか、Oculus VR公式のOculus Storeで配信することができます(アプリ審査あり)。Oculus Shareというポータルがありましたが、公開終了になりました。Oculus StoreのConceptsセクションに移行するようです。

また、SteamではOculus Riftに対応しているゲームに「VR サポート」というタグがついていますが、対応状況や起動方法がまちまちのようです(要調査)。

ダウンロードしたソフトが動かないんだけど?

過去の開発キットであるOculus Rift DK1/DK2向けにビルドされたアプリケーションは、製品版のOculus Riftおよび新しいOculusソフトウェアでは動作しません。製品版のOculusソフトウェア向けにビルドされたものを探してみてください。

また、Unknown Sourcesの設定がオンになっているかを確認してください。

その他のTips

製品版向けランタイムでは非同期タイムワープがサポートされ、フレームレートが低くても頭の回転ではカクつきません。ただ、これにあまり頼らないようにとのことです。

ストアからダウンロードしたアプリは、デフォルトではC:¥Program Files (x86)¥Oculus¥Softwareに格納されます。Oculusソフトウェアのセットアップ時に別のドライブに変更可能です(一度アンインストールして再セットアップする必要があります)。

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

PC側のOculusソフトウェアはElectron製、Rift側のOculus HomeはUnity製のようです。

Oculusソフトウェアの右上の歯車>Settings>Generalの画面で、Oculusソフトウェアのバージョンが確認できます。

Oculusソフトウェアをセットアップすれば、以後ドライバ・ランタイムは自動アップデートされるとのことです。

Oculus Storeのアプリのキーをストア以外の場所でも販売できるようです。その際、ロイヤルティはかからないようです。

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

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


参考リンク

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