» VR開発メモトップへ

Unity+Steam VR開発メモ(HTC Vive、Valve Index対応)

最終更新日:2021年09月23日

UnityでSteam VR対応ソフトを開発する方法やTipsをまとめています。SteamVR Plugin 2.6以降対応です。

更新履歴

(2021年9月23日)SteamVRのTipsに「コントローラーが使用できない」を追加
(2021年7月28日)「アプリ起動後にVRモードを有効にしたい」を追加、ページタイトルを変更、古い項目を削除
(2021年7月11日)Steamでアプリケーションを配信するときのactions.jsonのパス設定について追記
(2021年6月8日)「簡単にフェードイン・フェードアウトをするには」にOpenVR.Compositor.FadeToColorを追加
(2020年11月21日)「PC の画面に別視点の映像を表示するには」を追加


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

Unity で SteamVR 対応ソフトを作るには、Asset Store にある SteamVR プラグインを使用します。新規プロジェクトを「3D」テンプレート(レガシーレンダーパイプライン)で作成し、SteamVR プラグインをインポートしてください。

プラグインをインポートすると、OpenVR XR Plugin がインストールされたというダイヤログが出るので閉じます。また、Unity の設定を SteamVR の推奨設定に変更するウィンドウが開きます(リニアカラーにする等)。左下の「Accept All」をクリックしてください。「You made the right choice!(正しい選択をしたね!)」というノリノリのメッセージウィンドウが出ますので閉じます。

Unity > Edit Project Settings… で、下記イメージのように左の列に XR Plug-in Management と OpenVR の表示があり、OpenVR Loader のチェックが入っている状態が正常です(なかなかすんなり行かないことがあって、プロジェクトファイルを開き直す等が必要っぽい)。

Projectビューでサンプルシーンの SteamVR/Simple Sample を開きます。

再生する前に入力周りの設定が必要です。Window > SteamVR Input メニューを開いてください。“It looks like your project is missing an actions.json. Would you like to use the example files?” というメッセージが出るので Yes を選択します。さらに、開いた SteamVR Input ウィンドウの左下の “Save and generate” ボタンをクリックします。Hold on がしばらくして終了するのを待ち、SteamVR Input ウィンドウを閉じて再生ボタンを押します。

既存のプロジェクト・シーンを SteamVR 対応にするには、Main Camera を削除または無効化して、Project ビューの SteamVR/Prefabs/[CameraRig] プレハブをシーンの床の中央となる位置に配置してください。

なお、Unity でシーンを再生する際には Game ビューの「Maximize on Play」をオンにするとフレームレートが向上する場合があります。


位置トラッキングについて

SteamVR では、ルームスケールもしくは着席状態のいずれかのトラッキングスペースを使用できます。デフォルトではルームスケールになっていて、変更するには Project ウィンドウで SteamVR_Resources/Resources/SteamVR_Settings を選択して、Tracking Space Origin を変更します。

Tracking Universe Standing(デフォルト)

ルームスケールのモードです。[CameraRig] を配置した場所が、SteamVR のルームセットアップで設定したプレイエリアの中央の地面になります。

Tracking Universe Seated

着席モードです。[CameraRig] をVR空間のプレイヤーの頭の位置となる場所に配置します。

位置合わせをするには、ヘッドセットをかぶってコントローラーのメニューボタンでダッシュボードを表示し、で右下の「Reset Standing Position」をポイントしてトリガーを引きます。

また、InputTracking.Recenter メソッドでもリセットできますので、これをキーやボタン等で実行できるようにしておくと便利です。サンプルスクリプトです。

using UnityEngine;
using UnityEngine.XR;

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

コントローラーの入力について

SteamVR プラグインは、「アクション」という抽象的な単位でモーションコントローラーの入力を扱います。例えば「物を持つ」「テレポートする」といったアクションを定義して、Vive コントローラー、Oculus Touch、Knuckles といったコントローラーのトリガーやボタンにアクションを割り当てることで、どんなモーションコントローラーが登場しても対応できるようにしようという考え方です(Unity の新 Input System に似ていますが別のシステムです)。

Window > SteamVR Input で SteamVR Input ウィンドウを開いてください。

SteamVR プラグインをインポートすると、デフォルトのアクションセットが定義されています。若干分かりにくいのですが、ここでは「default」「platformer」「buggy」の3つのアクションセットが作成されていて、それぞれボタンを押すとアクション一覧が表示されます。

アクションを選択するとそれぞれ Type が設定されており、boolean(オンかオフか)、vertor1-3(1軸から3軸)、pose(位置と方向)等が選択できます。

左下の「Save and generate」をクリックすると、それぞれのアクションを参照するために必要なクラス群が Project ウィンドウの SteamVR_Input フォルダに生成されます。

右下の「Open Binding UI」をクリックすると、コントローラーのトリガーやボタンとアクションとの対応を設定できます。

一通り設定したのち、右下の「Replace Default Binding(デフォルトバインドの置換)」をクリックすると、StreamingAssets/SteamVR フォルダにバインドの定義ファイル(bindings_*.json)が書き出されます。これを繰り返して、一通りのコントローラーでデフォルトのバインド設定を行います。

まずアプリケーションで使用する抽象的なアクションを SteamVR Input ウィンドウで作成し、アクションとそれぞれのモーションコントローラーの操作を関連付けた上で、アプリケーションでアクションにアクセスするという流れになります。

実際のアクションの入力は以下のようなコードで取得できます。GameObject にアタッチして、インスペクタで入力を取得するコントローラー(Any / LeftHand / RightHand)とアクションを割り当ててください。

using UnityEngine;
using Valve.VR;

public class SteamVRInputTest : MonoBehaviour
{
    [SerializeField] SteamVR_Input_Sources hand;
    [SerializeField] SteamVR_Action_Boolean action;

    void Update()
    {
        if (action.GetState(hand))
        {
            Debug.Log("Action!");
        }
    }
}

アクションの現在の状態を取得する GetState や、オンになった瞬間を取得する GetStateDown、オフになった瞬間を取得する GetStateUp、また1フレーム前の状態を取得する GetLast / GetLastDown / GetLastUp といったメソッドが使用できます(TODO:他にもいろいろあるので追記)。

以下のように直接アクセスすることもできます(SteamVR_Input フォルダ以下に生成されたクラスを使用しています)。

SteamVR_Actions.default_Teleport.GetStateDown(SteamVR_Input_Sources.Any)

また、SteamVR_Behaviour_* という名前のコンポーネントがあり、GameObject にアタッチするとアクションに対してイベントを呼び出したりできます。SteamVR プラグイン v2 の CameraRig では「Controller (left)」「Controller (right)」に SteamVR_Behaviour_Pose がアタッチされていて、これによってコントローラーの動きに追従します。

モーションコントローラーを振動させるには

SteamVR_Action_Vibration.Execute メソッドを使用します。SteamVR Input ウィンドウで設定された vibration タイプの Out アクションを参照して呼び出します。サンプルのアクションセットであれば Haptic(\actions\default\out\Haptic)を設定します。

using UnityEngine;
using Valve.VR;

public class VibrationTest : MonoBehaviour
{
    [SerializeField] SteamVR_Input_Sources hand;
    [SerializeField] SteamVR_Action_Boolean action;
    [SerializeField] SteamVR_Action_Vibration vibration;

    void Update()
    {
        // actionがオンになったら
        if (action.GetStateDown(hand))
        {
            // 0秒後から0.2秒間、100Hz、強さ1で振動させる
            vibration.Execute(0, 0.2f, 100, 1f, hand);
        }
    }
}

Vive トラッカーを使用するには

トラッカーごとに役割を設定し、アクションを割り当てる必要があります。下記のような手順を行います。

  • トラッカーを接続する
  • SteamVR のメニュー>デバイス>トラッカーの管理>VIVEトラッカーの管理で、各トラッカーの役割を設定(ここで「トラッカーを識別」をクリックすると該当のトラッカーのLEDランプが点滅します)
  • SteamVR プラグインの SteamVR Input ウィンドウで Open binding UI を開く
  • 「現在のコントローラー」で、左足なら Vive Tracker on Left Foot 等を選択
  • 「バインドの新規作成(Create New Binding)」で「アクションポーズの追加」をして「未使用」を「Pose」に変更する
  • 「デフォルトバインドの置換」
  • [CameraRig] の「Controller (left)」等を複製して、SteamVR_Behaviour_Pose コンポーネントの Input Source を Left Foot 等にそれぞれ変更する

アクションの入力を確認するには

  • Window > SteamVR Input Live View
  • 「Open Binding UI」でEditでモーションコントローラーのバインド設定を開いて、右下の「Input Debugger」

のいずれかで確認できます。

その他の Tips

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

展示でヘッドセットをかぶっていない人に PC ディスプレイで観客視点の映像を見せたり、アバターでプレイしている様子を表示したいといったことがあると思います。

Camera をシーンに追加し、余分な Audio Listener を削除した上で以下の設定を行います。レンダーパイプラインによって設定方法が変わります。

レガシーレンダーパイプライン

Camera コンポーネントの Target Eye を「None (Main Display)」に設定します。PC 側のカメラの Depth (priority) の数値をヘッドセット側のカメラより大きくしておく必要があります。

URP

レガシーレンダーパイプライン同様ですが、Target Eye が表示されていないことがあります。インスペクターを右上メニューから Debug にすると Target Eye が見つかりますので、0 を設定すると Normal 表示のほうに「None (Main Display)」となって出てきます。

あるいは、Unity 2020.2 以降で preview パッケージをインストールできるようにして Universal RP パッケージを Version 10.0.0 以降に更新すると Target Eye が通常通り表示されます。

HDRP

Camera コンポーネントの XR Rendering をオフにします。

アプリ起動後にVRモードを有効にしたい

アプリを非VRモードで起動して、あとからVRモードに切り替えたい場合があります。Project SettingsのXR Plugin ManagementでInitialize XR on Startupをオフにして、XR Plugin ManagementのこちらのページにあるManualXRControlクラスを使用してください。以下の要領でVRモードに切り替えられます。

var manualXRControl = new ManualXRControl();
StartCoroutine(manualXRControl.StartXRCoroutine());

これだけだとビルド後の実行ファイルを起動しただけでSteamVRが起動してしまうのですが、[GameName]_Data¥boot.configにあるxrsdk-pre-init-library=XRSDKOpenVRを消すと、SteamVRがあとから起動するようになります。

ドキュメントおよび参考情報

下記リンクに SteamVR プラグインの公式ドキュメントがあります。上部メニューの Articles、Tutorials 等を確認してください。

また、プラグインの SteamVR フォルダに「SteamVR Unity Plugin」「SteamVR Unity Plugin - Input System」というPDFが入っています。

開発者向けフォーラムがあり、しばしば参考になる情報が見つかります。Valve の開発者も書き込んでいます。

GitHub のリポジトリの Issues でしばしば不具合情報が見つかります。

SteamVR の安定版およびベータ版のアップデート内容は下記ページで確認できます。


Vive トラッカーの使い方

Vive トラッカーを使用することで、いわゆるフルトラッキングをしたり、物体の位置を取得できます。

Vive トラッカーをペアリングするには

トラッカーひとつにつき付属のドングルひとつが必要です。ドングルを PC に接続してください。できれば、付属の USB ケーブルとクレードルを使用してドングルを PC から離すと認識が良くなります。

トラッカー中奥の電源ボタンをクリックして電源を入れ、SteamVR のメニューで「デバイス>コントローラーのペアリング」を実行し、トラッカーの電源ボタンを長押しして青点滅状態にしてください。

ペアリングに成功すると SteamVR でトラッカーの形をしたアイコンが表示されます。

Vive トラッカーのステータスライトについて

ステータスライトの表示は以下のようになっています。

状態
接続(ペアリング済み)
未接続
青点滅 ペアリング中
赤点滅 バッテリー残量低下
オレンジ 充電中

電源ボタンの操作について

トラッカー中央の電源ボタンで以下の操作が可能です。

操作 効果
押す 電源オン
5秒間押す 電源オフ
5秒弱押す ペアリング(青点滅になる)
PCにUSB接続して10秒間押す ハードウェアリセット

その他

SteamVR を終了するとトラッカーの電源は自動的にオフになります。

背面の Pogo ピンを使用する場合の開発者向けのドキュメントがこちらにあります。


SteamVRのTips

コントローラーが使用できない

「バインドが見つかりません」「入力バインドの読み込みに失敗しました」「Steamを利用できません。一部の機能が無効の可能性があります」といったエラーが出てコントローラーが使用できず、「バインドの新規作成」を押しても反応しない場合があります。

Steamが起動していないとこの状態になります。Steamを起動してログインしている状態でSteamVRを起動してください。

ベータ版のSteamVRを使うには

SteamVRはベータ版で先行して不具合の修正などが行われています。ベータ版のSteamVRを使用するには、Steamを起動して、「ライブラリ」タブのSteamVRで右クリックしてプロパティを開き、「ベータ」タブの「参加希望のベータを選択してください」を「beta - SteamVR Beta Update」に変更してください。SteamVRを終了すると、ダウンロードとインストールが開始されます。

Windows Mixed Realityヘッドセットを使用するには

Windows Mixed Reality for SteamVR をインストールすると、SteamVRでWindows Mixed Realityヘッドセットを使用できるようになります。

その他

HTC Vive か Oculus Rift か判別するには

SteamVR.instance.hmd_TrackingSystemName で、HTC Vive なら “lighthouse”、Oculus Rift なら “oculus” が取得できます。

イメージエフェクトを使うには

SteamVR プラグインでは、[CameraRig] の中の Camera (eye) にイメージエフェクトのスクリプトをアタッチしてください。

Unity の新しい Post Processing Stack のスクリプト(Post Processing Behaviour)も使用できます。Antialiasing の Temporal Anti-aliasing、Screen Space Reflection、Motion Blur は VR では動作しないので注意です。

SteamVR プラグインに Unity の設定を変更されないようにするには

SteamVR/Editor/SteamVR_Settings.cs スクリプトを拡張子を変えるなどして無効化してください。

簡単にフェードイン・フェードアウトをするには

SteamVR プラグインに入っている SteamVR_Fade コンポーネントを Camera オブジェクトにアタッチすると、簡単にフェードアウトやホワイトアウトができます。下に視界を白くフラッシュさせる例を示します。なお、これはヘッドセット内の映像にしか影響しないため注意してください。

// 即座に画面を真っ白に
SteamVR_Fade.Start(Color.white, 0f);
// 2秒かけてクリアに戻す
SteamVR_Fade.Start(Color.clear, 2f);

SteamVR_Fade.csはUnityのGLクラスでフレームバッファをフェードしますが、SteamVRのコンポジッターレベルでフェードするOpenVR.Compositor.FadeToColorを使うこともできます。

OpenVR.Compositor.FadeToColor(durationSec, 0f, 0f, 0f, 0f, false);

シーンを切り替えるときに白い部屋が表示される

SceneManager.LoadScene でシーンを普通に変更すると、HTC Vive の画面が一瞬アプリを起動していないときのデフォルト画面になる場合があります。メインのシーンを切り替えない作りにするか、または、SteamVR プラグインに SteamVR_LoadLevel.cs というサポートスクリプトが入っていますので、こちらを使用してみてください。

SteamVR_LoadLevel.Begin("[シーン名]") でシーンを切り替えられるほか、いくつかの機能があるようです。

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

Game ビューの「Maximize on Play」をオンにして再生してみてください。最大化せずに再生すると、エディタの描画が負荷になり、フレームレートが低下します。

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

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

UnityEngine.XR.XRSettings.eyeTextureResolutionScale = 0.5f; // デフォルトは 1.0f
書いた人:こりん(@korinVR
» VR開発メモトップへ