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

プラットフォーム モードの移動ではHoloLens 2、石油プラットフォーム、その他の車両などの移動プラットフォームで正常に動作できます。

プラットフォーム モードの移動の詳細を学習する

概念

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

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

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

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

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

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

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

SDK の入手場所

Moving Platform SDK は C# と C++ の言語プロジェクションをサポートしており、開発者は Win32 または UWP プラットフォーム用のアプリケーションを開発できます。 Mixed Reality Feature Tool を使用して 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 デバイスや 1 から 1 など、プラットフォーム モードの移動を利用できないデバイスはHoloLens常に '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 を返します。 この関数は、Mobile デバイス管理 (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;
    }
}

こちらもご覧ください