Unity でのプラットフォーム モードの移動

移動プラットフォームモードを使用すると、船、石油プラットフォーム、その他の車両などの移動プラットフォームでHoloLens 2が正しく動作します。

プラットフォーム モードの移動に関する詳細情報

概念

Mixed Reality システムが正しく動作するには、ヘッドセットを環境に対して相対的に追跡する必要があります。 この相対的な追跡により、ヘッドセットのユーザーが環境内でしっかりとロックされているように見えるようにグラフィックスをレンダリングできます。 トラッキングは通常、外向きのカメラと慣性計測ユニット (IMU) からの測定値を使用して計算されるポーズを組み合わせることによって実現されます。 このメソッドは、環境が参照の慣性フレーム内にある場合に適切に機能します。 惑星の動きのような小さな効果は、通常無視されます。

環境が慣性参照フレーム内にない場合、通常のヘッド追跡システムは失敗します。 移動プラットフォーム モード機能は、慣性フレームに対する環境の動きを計算することで、この問題を解決します。 したがって、プラットフォームの移動モードでは、環境が潜んでいる船であっても、HoloLens 2環境に固定されたホログラムをレンダリングできます。

移動プラットフォーム モードをアクティブにする方法

広範なユース ケースを有効にするため、さまざまな方法で移動プラットフォーム モードをアクティブにできるようになっています。 慎重に検討して方法を選ぶことが重要です。 判断の基準となるのは、現在 HoloLens 2 が動くプラットフォーム内にあるかどうか知っているのは誰か、ということです。 例については、次の表を参照してください。

HL2 が動くプラットフォーム内にあるかどうかわかるのは誰か 移動プラットフォーム モードを設定する最適な方法 メリット コスト
システム管理者 モバイル デバイス管理 ユーザーが関わる必要がありません。 すべてのアプリが変更なしで動作します。 デバイスが正しくないモードになるのを防止できます。 ユーザーとアプリはモードを変更できません。
エンド ユーザー 設定アプリ 多くの場合、いつどこでデバイスを使用しているのかを最もよく知っているのはユーザーです。 すべてのアプリが変更なしで動作します。 ユーザーはモードの存在を知らない可能性があります。
Application この記事で説明されている SDK を使用します。 環境が前もってわからない場合は、ユース ケース固有の手掛かりを使ってモードを切り替えることができます。 ユーザーがこれを決定して設定のモードを変更する必要がなくなります。 アプリの設計が不適切な場合、エクスペリエンスが非常に悪く、デバイスが予期しないモードになる可能性があります。

プラットフォーム モードの移動に関するベスト プラクティス

プリンシパル 説明
ユーザーの選択を尊重する ユーザーに対してモードを変更する前に選択肢を提供する必要があり、アプリのランタイムに対して引き続きその選択を尊重する必要があります
ユーザーに警告を表示する アプリの開始/再開時にすぐにモードを変更しないようにします。 これは、ユーザーがデバイスが追跡を失っている理由がわからない可能性があるため、ユーザー エクスペリエンスが低下します。
変更モードを最小限に抑える プラットフォーム モードの移動設定を変更すると、デバイスの追跡が失われるので、ユーザー エクスペリエンスが低下します。 そのため、モードを変更する頻度を最小限に抑えるようにすることをお勧めします。 理想的には、デバイスが静止環境から移動環境に移行している場合、またはその逆の場合にのみ、モードが変更されます。
環境が不明な場合は、移動プラットフォーム モードを使用します 移動プラットフォーム モードは、静止環境と移動環境の両方で動作します。 通常の追跡アルゴリズムは静止環境でのみ機能するため、環境が移動しているかどうかが不明な場合は、[プラットフォーム モードの移動] を選択する方が安全です。
既知の静止環境では移動プラットフォーム モードを使用しない プラットフォーム モードの移動は、静止環境の標準モードよりもパフォーマンスが低くなります。 これは小さな劣化ですが、ほとんどのユーザーには顕著です。
デバイスを残すモードを検討する この SDK を使用すると、開発者はデバイスのブート全体で堅牢なエクスペリエンスを設計できます。 次回起動時にデバイスが移動プラットフォーム上にあるかどうかを検討し、デバイスを適切なモードのままにします。

SDK の入手場所

Moving Platform SDK では、C# と C++ の言語プロジェクションがサポートされており、開発者は Win32 または UWP プラットフォーム用のアプリケーションを開発できます。 Mixed Reality機能ツールを使用して SDK をダウンロードしてインストールします。

この SDK を使用操作方法

SDK をインストールしたら、次のように MovingPlatformManger を使用するようにスクリプトを設定できます。

// Top of file
using Microsoft.MixedReality.MovingPlatform;
// Code body
m_movingPlatformManager = new MovingPlatformManager();

現在のモードの読み取り

モードの現在の値は、次のように読み取ることができます。

MovingPlatformMode currentMode = m_movingPlatformManager.Mode;

MovingPlatformMode は、次のように定義される列挙型です。

public enum MovingPlatformMode
{
    Standard,                // The legacy mode that devices use out-of-the-box.
    MovingPlatformOptimized  // Allows tracking on moving platforms.
}

VR デバイスや HoloLens 1 など、移動プラットフォーム モードを使用できないデバイスは、常に "Standard" を返します。

モードを設定する

[プラットフォーム モードの移動] の値は次のように設定できます。

bool success = m_movingPlatformManager.TrySetMode(MovingPlatformMode.MovingPlatformOptimized);

デバイス モードが要求されたモードと一致する場合、TrySetMode は true を返します。 モードが既に目的の状態にある場合、何も行われず、デバイスが追跡を失うことはありません。

モード変更時のコールバック

場合によっては、別のアプリまたはユーザーが [プラットフォーム モードの移動] の値を変更したかどうかを確認すると便利な場合があります。 これを行うには、次のようにします。

// Code Body
m_movingPlatformManager.ModeChanged += CallbackOnMPMChanged;
...
void CallbackOnMPMChanged(object sender, MovingPlatformEventArgs args)
{
    movingPlatformModeChanged = true;
    movingPlatformModeValue = args.ModeEntered;
}
...
void Update()
{
    // It's not reccomended to do work in the callback.
    if (movingPlatformModeChanged)
    {
        movingPlatformModeChanged = false;
        // Do some work
    }
}

モードが設定可能かどうかを確認する

変更を試みる前に、モードが設定可能かどうかを知ると便利な場合があります。 たとえば、ユーザーに自分の好みを尋ねる際に何らかの値があるかどうかを知りたい場合です。 プラットフォーム の移動モードが IsSetModeSupported 関数で設定可能かどうかを確認できます。

bool supported = m_movingPlatformManager.IsSetModeSupported();

この関数は、デバイスがモードを変更できる場合は true を返し、不可能な場合は false を返します。 この関数は、モバイル デバイス管理 (MDM) ポリシーを考慮します。 たとえば、MDM が MovingPlatformMode を強制的に "On" にした場合、この関数は false を返します。

デモ スクリプト

このスクリプトは、SDK のすべての重要な要素を 1 か所で示します。 この例は、上記のベスト プラクティスに従っていません。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Microsoft.MixedReality.MovingPlatform;
using System;

public class MovingPlatformDemo : MonoBehaviour
{
    public GameObject cube; // A simple cube to display colors.
    private MovingPlatformManager m_movingPlatformManager;
    private Renderer cubeRenderer;
    private bool movingPlatformModeChanged;
    private MovingPlatformMode movingPlatformModeValue;

    // Start is called before the first frame update
    void Start()
    {
        m_movingPlatformManager = new MovingPlatformManager();
        cubeRenderer = cube.GetComponent<Renderer>();

        // Get initial value of mode, 
        // Just this mechanism would be adequate if a one time check is acceptable. 
        MovingPlatformMode initialMovingPlatformMode = m_movingPlatformManager.Mode;

        // Find if It's possible to change the mode. 
        bool isSettable = m_movingPlatformManager.IsSetModeSupported();

        // Here you would add some use case specific logic using initialMovingPlatformMode and isSettable
        // to decide if you should ask the user if they want to change the mode. 

        // To set the mode.
        bool success = m_movingPlatformManager.TrySetMode(MovingPlatformMode.MovingPlatformOptimized);

        // Visual indicator of current state: Green = Moving Platform Optimized, Red = Regular.
        SetColourFromState(m_movingPlatformManager.Mode, cubeRenderer);

        // We set a callback to be notified if there's a change in mode. This is typically optional.
        m_movingPlatformManager.ModeChanged += CallbackOnMPMChanged;
        movingPlatformModeChanged = false;
    }

    // Update is called once per frame
    void Update()
    {
        // This must be done in the UI thread.
        if (movingPlatformModeChanged)
        {
            movingPlatformModeChanged = false;
            SetColourFromState(movingPlatformModeValue, cubeRenderer);
        }
    }

    // Sets renderer to:
    // Green = Moving Platform Mode Enabled
    // Red = Moving Platform Mode Disabled
    void SetColourFromState(MovingPlatformMode mode, Renderer thisRend)
    {
        if (mode == MovingPlatformMode.MovingPlatformOptimized)
        {
            thisRend.material.color = new Color(0f, 1f, 0f, 1f);
        }
        else
        {
            thisRend.material.color = new Color(1f, 0f, 0f, 1f);
        }
    }

    void CallbackOnMPMChanged(object sender, MovingPlatformEventArgs args)
    {
        movingPlatformModeChanged = true;
        movingPlatformModeValue = args.ModeEntered;
    }
}

関連項目