Hiromuブログ

最近はこちら(https://zenn.dev/hiromu)が本体

Windows Mixed Reality for SteamVR

普段 MixedRealityToolkit-Unity しか触っていないと見落としがちですが、少し気になっていたのでWindows Mixed Reality for SteamVRを触ってみました。

Windows Mixed Reality for SteamVR とはWindows Mixed Reality対応のヘッドセットやコントローラーで「SteamVR」のゲームをプレイするためのツールです。

forest.watch.impress.co.jp

準備

準備については以下のサイトが参考になります。

indiegame-japan.com

以上の準備が終わるとWindows Mixed RealityのヘッドセットでSteamVRのゲームを楽しむことができます。 公開されているゲームを楽しむだけであれば以上で作業としては終了です。 以下では、自分で開発を行う場合の手順について記載します。

開発

確認した動作環境:

  • Unity 2017.4.5f1

サンプルシーンの確認手順:

  1. Unityで新規プロジェクトを作成

  2. Asset StoreからSteamVR Pluginをインポート assetstore.unity.com

  3. 完成プロジェクトのインポートの警告が表示されるがインポートを選択

  4. API Update Required が表示されたので[I Made a Backup. Go Ahead!]を選択

  5. SteamVR_Settingsが表示されるので[Accept All]を選択
    ほめられました

  6. [Assets/SteamVR/Scenes]にexampleシーンがあるので起動
    ヘッドセットおよびコントローラーを接続していない状態だとエラーが表示されました。


    ヘッドセットとコントローラーを接続し、SteamVRを再起動したところ問題無くサンプルが動作しました。

オリジナルシーンの開発手順:

  1. SteamVR Pluginのインポートが終わった状態で新規でシーンを作成し、Cubeを一つ追加してとりあえずシーンを再生
    何もしてないのにヘッドセットでシーンが見られました!ただしコントローラが表示されていません。

  2. SteamVR/Prefabsにある3つのPrefabs([CameraRig], [Status], [SteamVR])をシーンに配置しMain Cameraを削除
    コントローラが表示されました。

  3. モーションコントローラー入力のスクリプト作成
    コントローラー入力については以下のサイトを参考にしました。(HTC Viveと書かれていますがWindows Mixed Realityでも動作します) framesynthesis.jp

以下はWindows Mixed Reality用に内容修正したものです。

using UnityEngine;

/// <summary>
/// Windows Mixed Realityのモーションコントローラ用サンプル
/// </summary>
public class ControllerExample : MonoBehaviour {
    void Update()
    {
        var trackedObject = GetComponent<SteamVR_TrackedObject>();
        // indexはトラッキング状況に応じて変わる
        var device = SteamVR_Controller.Input((int)trackedObject.index);

        var side = "Unknown";
        var leftIndex = SteamVR_Controller.GetDeviceIndex(SteamVR_Controller.DeviceRelation.Leftmost);
        var rightIndex = SteamVR_Controller.GetDeviceIndex(SteamVR_Controller.DeviceRelation.Rightmost);
        if ((int)trackedObject.index == leftIndex)
        {
            side = "Left : ";
        }
        else if ((int)trackedObject.index == rightIndex)
        {
            side = "Right : ";
        }

        // メニュー
        if (device.GetPressDown(SteamVR_Controller.ButtonMask.ApplicationMenu))
        {
            Debug.LogFormat("{0}メニューボタンを押した", side);
            // 振動
            device.TriggerHapticPulse(1000);
        }
        if (device.GetPress(SteamVR_Controller.ButtonMask.ApplicationMenu))
        {
            Debug.LogFormat("{0}メニューボタンを押している", side);
        }
        if (device.GetPressUp(SteamVR_Controller.ButtonMask.ApplicationMenu))
        {
            Debug.LogFormat("{0}メニューボタンを離した", side);
        }

        // グリップ
        if (device.GetPressDown(SteamVR_Controller.ButtonMask.Grip))
        {
            Debug.LogFormat("{0}グリップボタンを押した", side);
        }
        if (device.GetPress(SteamVR_Controller.ButtonMask.Grip))
        {
            Debug.LogFormat("{0}グリップボタンを押している", side);
        }
        if (device.GetPressUp(SteamVR_Controller.ButtonMask.Grip))
        {
            Debug.LogFormat("{0}グリップボタンを離した", side);
        }

        // トリガー
        if (device.GetPressDown(SteamVR_Controller.ButtonMask.Trigger))
        {
            Debug.LogFormat("{0}トリガーボタンを押した", side);
        }
        if (device.GetPress(SteamVR_Controller.ButtonMask.Trigger))
        {
            Debug.LogFormat("{0}トリガーボタンを押している", side);
        }
        if (device.GetPressUp(SteamVR_Controller.ButtonMask.Trigger))
        {
            Debug.LogFormat("{0}トリガーボタンを離した", side);
        }

        // トリガーアナログ値
        var triggerValue = device.GetAxis(Valve.VR.EVRButtonId.k_EButton_SteamVR_Trigger).x;
        if (triggerValue != 0)
        {
            Debug.LogFormat("{0} トリガーアナログ値({1})",side, triggerValue);
        }

        // タッチパッド
        if (device.GetPressDown(SteamVR_Controller.ButtonMask.Touchpad))
        {
            Debug.LogFormat("{0}タッチパッドを押した", side);
        }
        if (device.GetPress(SteamVR_Controller.ButtonMask.Touchpad))
        {
            Debug.LogFormat("{0}タッチパッドを押している", side);
        }
        if (device.GetPressUp(SteamVR_Controller.ButtonMask.Touchpad))
        {
            Debug.LogFormat("{0}タッチパッドを離した", side);
        }

        // タッチパッド接触
        if (device.GetTouchDown(SteamVR_Controller.ButtonMask.Touchpad))
        {
            Debug.LogFormat("{0}タッチパッドに触れた", side);
        }
        if (device.GetTouch(SteamVR_Controller.ButtonMask.Touchpad))
        {
            Debug.LogFormat("{0}タッチパッドに触れている", side);
        }
        if (device.GetTouchUp(SteamVR_Controller.ButtonMask.Touchpad))
        {
            Debug.LogFormat("{0}タッチパッドから離した", side);
        }

        // タッチパッド位置
        var position = device.GetAxis();
        if (position.x != 0 || position.y != 0)
        {
            Debug.LogFormat("{0}タッチパッド x: {1}, y: {2}", side, position.x, position.y);
        }
    }
}

サムスティックについては以下のサイトを見ると制御できそうなのですが動作確認できませんでした。(サムスティックはSteamVRのカメラ移動やメニュー表示に利用しているため利用しないほうが良いかもしれません)

docs.microsoft.com

終わりに

ということで、MixedRealityToolkit-Unityを利用しなくてもWindwos Mixed Realityのアプリを作れることが分かりました。現状Microsoft StoreだけでなくSteamにアプリを公開したい場合はこちらを利用することになりそうです。 なお、MixedRealityToolkit-Unityのロードマップに記載されているMRTK Version NextではSteam対応が予定されているようです。