Unity+Gear VR開発メモ

最終更新日:2018年05月12日

UnityでGear VR対応アプリを開発する方法やTipsをまとめています。Gear VR自体についての解説やTipsは「Gear VRについて」を参照してください。

更新履歴

(2018年3月31日)リニアカラースペースでの不具合について注記、その他リンクや古くなっていた記述を修正
(2017年4月5日)デバッグモードでもトラッキングするようになったのを反映(thx: @needleさん)
(2017年2月27日)adbコマンドのtypoを修正(thx: @izmさん)
(2016年11月24日)Unity 5.4のパフォーマンス問題について更新
(2016年10月7日)「動画を再生するには」を更新、参考リンクの修正


UnityでGear VR対応アプリを作るには

UnityのGear VR対応について

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

さらに、Oculus Storeでの配信等、Gear VRやOculusプラットフォーム固有の機能を使用したい場合は、Oculus VRのダウンロードページにあるOculus Utilities for Unityを追加でインポートして使用します。

Gear VRアプリをビルドするには

まず、Build SettingsでプラットフォームをAndroidに変更して、Player Settings…のXR Settingsにある「Virtual Reality Supported」をチェックしてオンにしてください。また、Minimum API Levelを「Android 4.4 ‘KitKat’ (API level 19)」以上に変更し、Bundle Identifierの「com.Company.ProductName」のCompanyとProductNameを適当な組織名とプロダクト名で書き換えます。

また、Build Settingsでテクスチャの圧縮方式(Texture Compression)をASTCに変更します。

さらに、個々の端末と紐付けられるOculus Signature Fileという署名ファイルが必要になります。コマンドラインから、adbコマンドを「adb devices」で実行して、デバイスIDを確認します。

C:\Users\{ユーザー名}\AppData\Local\Android\sdk\platform-tools>adb devices
List of devices attached
* daemon not running. starting it now on port 5037 *
* daemon started successfully *
{デバイスID}        device

下のページにアクセスし(Oculus VRのアカウントが必要)、デバイスIDを入力して「ファイルをダウンロード」で署名ファイルをダウンロードします。

ダウンロードした「oculussig_{デバイスID}」という名前の署名ファイルを、UnityのプロジェクトのAssets/Plugins/Android/assetsフォルダに格納します。

端末を接続して、アプリをBuild and Runでビルド・実機に転送します。

タップして実行すると「端末を挿入 このアプリケーションを起動するには、端末をGear VRに挿入します」というダイヤログが出るので、その状態のままで端末をGear VRに差し込みます(ちょっと難しいです)。Gear VRを覗き込むとアプリが開始します。

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


開発Tips

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

Oculus VR社のvrdaveb氏のコメントによれば、Player SettingsでRendering PathをForwardにして、Quality SettingsのAnti AliasingでMulti Sampling(MSAA)をかけることが推奨されています。Deferredは帯域コストが高く、MSAAが使えないため不利になります。MSAAはImage Effectsのアンチエイリアス(FXAA)よりも軽量で、ポリゴンのエッジがずっと綺麗になります。Gear VRでは2x MSAAはほぼノーコストとのことです。

カラースペースはガンマにします。リニアにすると画面が暗くなる現象が発生します(ドライバの不具合のため修正される見込みはなさそうとのことです……)。

左右のフレームバッファの解像度は1024x1024にUnityEngine.XR.XRSettings.renderScaleを縦横それぞれ掛けた大きさになるようです。1.0より大きくすることもできますが、renderScaleの二乗に比例して重くなるので注意してください。

タッチパッドの入力を取るには

Gear VR右側面についているタッチパッドの操作は、Unity上ではマウスとして認識されます。Input.mousePositionで座標を取得できます。

マウス座標はタッチパッド上でタップを開始した起点を(1280, 720)として、相対座標で変化します。つまり、タッチパッド上のどこを触っても最初は必ず(1280, 720)になります。その状態から指をスライドさせると、座標が800x800程度の範囲で以下の方向に変化します。

方向 座標
上方向 +Y
下方向 -Y
後方(手前方向) +X
前方(奥方向) -X

指を速くスライドさせるほど数値が大きく動きます。座標は2560x1440(端末のディスプレイ解像度)からはみ出さないようになっています。

タップ操作はマウスのボタン(Input Managerの「mouse 0」)で取得できます。「戻る」ボタンはEscキー(「escape」)として認識されます。

また、Unity公式サンプルのVR Samplesに、上記の入力からスワイプやダブルタップなどのジェスチャーを認識する補助スクリプト(VRStandardAssets/Scripts/VRInput.cs)が入っています。空のゲームオブジェクトにアタッチして、OnSwipeなどのイベントを購読することで使用できます。VRSampleScenes/Scripts/Examples/ ExampleTouchpad.csスクリプトおよびVRSampleScenes/Scenes/Examples/Touchpadシーンを見ると使い方が分かります。

ちなみにVRInput.csのスワイプ方向は、前方(奥方向)でLEFTが返ってくるようになっています(ちょっと直感に反する気がするのですが)。

ゲームパッドを使うには

Gear VRに対応しているBluetoothゲームコントローラがこちらに記載されています。Samsung El-GP20がいわゆる純正コントローラになりますが、国内で販売されていないので、Micro C.T.R.L.r Mobile Gamepadなどを使用している人が多いようです(販売終了?)。

ゲームパッドの入力はUnity上で普通のジョイスティックとして取得できます。Input Managerにおける軸とボタンのマッピングは以下のようになっています。Samsung El-GP20とその他の多くのBluetoothコントローラで同じ配列とのことです。

Axis/Button
X axis 左アナログスティック X軸(左-1~右1)
Y axis 左アナログスティック Y軸(上-1~下1)
3rd axis 右アナログスティック X軸(左-1~右1)
4th axis 右アナログスティック Y軸(上-1~下1)
5th axis 十字キー X軸(左-1、右1)
6th axis 十字キー Y軸(上-1、下1)
joystick button 0 Aボタン
joystick button 1 Bボタン
joystick button 2 Xボタン
joystick button 3 Yボタン
joystick button 4 左トリガーボタン
joystick button 5 右トリガーボタン
joystick button 10 STARTボタン
joystick button 11 SELECTボタン

左右のアナログスティックの押し込みは取得できないようです。

マッピングがXboxコントローラと異なるため、PCと両対応のソフトを作る場合には何らかの方法で吸収する必要がありそうです。Oculus UtilitiesのOVRInputを使用してもいいかもしれません(未調査)。

ヘッドトラッキングをリセットするには

InputTracking.Recenter() でリセットできます。下記スクリプトでタップでリセットできます。

using UnityEngine;
using UnityEngine.XR;

public class Recenter : MonoBehaviour
{
    void Update()
    {
        if (Input.GetButtonDown("Fire1"))
        {
            InputTracking.Recenter();
        }
    }
}

アプリの終了やグローバルメニュー、ボリューム表示に対応するには

Oculus Storeにアプリを登録する際には、要件として、Backボタンによるアプリの終了、Backボタン長押しによるグローバルメニューの表示、ボリュームボタンを押したときのボリュームの表示などに対応する必要があります。

Oculus VRのダウンロードページからOculus Utilities for Unityをダウンロードしてください。パッケージをプロジェクトにインポートして、Main CameraをOVRCameraRigプレハブに入れ替えると上記が一通り実装されます。

動画を再生するには

Oculus VRのダウンロードページにあるOculus Sample Framework for Unity 5 Projectに、ハードウェアH.264デコーダーを使用して動画を再生するサンプルが入っています。

プロジェクトファイルを開いて、SampleScenes/Rendering/Movie PlayerのMovie Playerシーンを開いてください。MovieSurfaceオブジェクトのMoviePlayerSampleスクリプトでMP4ファイルが再生されています。サンプルの動画は平面ですが、メッシュをノーマルを反転させた球に変更すると全天球動画を再生することもできます。

このやり方ではGear VR専用となるため注意が必要です。他には、Easy Movie TextureAVPro Video (Android)といったUnityの有料アセットがあるようです。

Oculus VRのvrdaveb氏的にはEasy Movie Textureがおすすめのようです。

パススルーカメラを使うには

端末のカメラの映像をUnityのWebCamTextureクラスで取得できます。以下のスクリプトを16:9のサイズにしたPlaneにアタッチしてください。

using UnityEngine;

public class PassthroughCamera : MonoBehaviour
{
    void Start()
    {
        var texture = new WebCamTexture(1280, 720, 30);
        GetComponent<Renderer>().material.mainTexture = texture;
        texture.Play();
    }
}

Planeを頭の向きに追従させるには、Main Cameraの子にします。また、ライティングの影響を受けないように、PlaneにはシェーダーをUnlit/Textureにしたマテリアルを割り当てます。

カメラを使用すると、初回起動時に「{アプリ名}が写真の撮影と動画の記録の許可を要求しています。許可しますか?」というメッセージが出ます。

なお、WebCamTextureはあまりパフォーマンスが良くないようです。NetCamという有料アセットがあるようですが、試していません。

熱で止まるんだけどどうすればいいの?

Oculus Utilitiesをインポートして、CPUとGPUのパフォーマンスレベルを下げてみてください。

OVRManager.cpuLevel = 2;
OVRManager.gpuLevel = 2;

パフォーマンスレベルはCPU、GPUそれぞれ0から3の値で設定し、0が最も低クロックでバッテリー消費・発熱が低く、3が最も高クロックでバッテリー消費・発熱が高くなります。デフォルト値はCPU、GPUともに2です(OVRManager経由では正しいデフォルト値が読めないようなので注意)。

通例、CPUのほうがGPUより問題を起こしやすいとのことです。動画プレーヤーなど長時間再生するものは(0, 0)や(0, 2)などにするといいようです。(2, 3)および(3, 3)は設定はできるもののすぐ止まるので非推奨とのことです。基本的には、フレームレートを維持できる範囲でなるべく低めに設定します。また、低く設定できるように最適化を行います。

Wi-Fi経由でadbコマンドが使える場合、

adb logcat -s VrApi_Clocks

とすると、端末の実際のパフォーマンスレベルと動作クロック数の変化が確認できます。

その他、詳しくはOculus VRのPower Managementのページを参照してください。

Gear VRに装着したAndroid端末の出力ログを見るには?

Gear VRについているUSB端子は給電にしか使えません。adbコマンドをWi-Fi接続で使用することで、端末をGear VRに挿した状態でもアクセスすることができます。

まず、端末をUSBケーブルで接続して、

adb tcpip 5555(※ポート番号)

を実行します。端末の設定>Wi-Fiから現在の接続を選択してIPアドレスを確認し、

adb connect {IPアドレス}

で接続できます。以後、USBケーブルをはずしてもadb devicesやadb logcat等のコマンドを使用することができます。

Virtual Reality Supportedを有効にしてプレビュー再生するとクラッシュするんだけど

MacでOculus Runtimeが入っていないと落ちるようです。Oculus RiftのOS Xサポートはすでに停止されていますが、Unityは古いOculus Runtime 0.5に対応しているようですので、こちらをインストールしてみてください。

ビルドしたアプリをGear VRに挿入せずに実行するには

端末の 設定>アプリ>Gear VR Service>ストレージ>ストレージを管理で「VR Service Version」を6回前後タップして、出てきた「開発者モード」をオンにしてください。低残像の表示に切り替わり、Gear VR向けにビルドしたアプリを端末のみで実行できるようになります。

タッチパッドの操作は画面の直接タッチでできますが、Gear VRのタッチパッドと異なりタッチ座標は画面の絶対位置になります。

端末実機でのテストや、パフォーマンスの調査等に使用するのがいいかもしれません。

ビルドを速くするには

UnityのAndroidビルドはデフォルトでx86とARM両方のバイナリを生成します。Gear VRではx86を使用しませんので、無効化することでビルドの時間が若干短くなるようです(カーマック氏のツイートで22%速くなった事例が紹介されています)。

Player SettingsのAndroidのタブのDevidce FilterをARMv7に変更してください。


参考リンク

書いた人:こりん(@korinVR
VR開発メモトップ