Mixed Reality Toolkit (MRTK)の有用なビルディングブロック

Mixed Reality Toolkit-Unityは、Unity上でMixed Realityエクスペリエンスを構築するための基本的なコンポーネントや、共通のインタラクションや、UIコントロールを共有するオープンソースプロジェクトです。

こちらはMixed Reality Toolkit(MRTK)の開発者であるYoon氏による説明記事の書き出しを引用させていただきました。基本機能の説明が網羅されている上、日本語化もされており、とても読みやすい内容になっています。

MRTKは元々HoloToolKit(HTK)と呼ばれるHololens用のSDKからスタートしています。その後、WinMRへの対応が加えられたことで現在のMRTKの基盤が作られました。現在はそれをブラッシュアップしたSDKがMRTKv2として提供されています。(※以後本記事ではMRTKはMRTKv2を指すこととします)

MRTKを採用するメリットとしてMRデバイス要素(入力、UI、インタラクション)の共通化に加え、VR/ARといったMRに限らないXRデバイスの抽象化という側面が挙げられます。

現状のXRデバイスには独自のプラットフォームに対応したSDKがそれぞれ存在し、実装する側は適切なSDKを入手しアプリに組み込む必要があります。たとえばSteamVR、Oculus Integration、ARCore、ARKitなどが挙げられます。

単一のプラットフォームを対象にしたアプリを作る場合であれば問題ありませんが、複数のプラットフォームを対象とする場合、開発者側で各環境ごとに適切なSDKを利用するように実装を行う必要があるため都合が悪くなってきます。

それを解決するための取り組みとしてKhronosにより業界全体を巻き込むOpenXRが推進されるなど、増えていくデバイスをどのように抽象化し生産性を高めるかは現在のXR開発においてとても大きなポイントとなっています。今後MRTKを採用することはこの問題に対する1つの解決策になっていくかもしれません。

また、MRTKはオープンソースプロジェクトとなっているため、GitHubにて誰でも実装や議論の流れを追うことができます。

https://github.com/microsoft/MixedRealityToolkit-Unity

開発段階のブランチもコミットされているため、それらをプルすればまだリリースされていない機能を試せますし、実装中に見つけたバグや困った点はIssueを作り対応を求めたりすることができます。

実際に使ってみる

「ボタンを押したら、テキストを変更する」というシンプルなアプリを作りながらMRTKの挙動を確認していきたいと思います。

MRTK対応のシンプルなシーンを作成

通常の操作でシーンを作成後、メニューバーの「Mixed Reality ToolKit」から「Add to Scene And Configure」を選択します。

ここには MixedRealityToolkitConfigurationProfile によって作成されたScriptableObjectが一覧で表示されます。

MRTKではカメラや入力といった共通化可能なコンポーネントの設定をまとめたScriptableObjectを MixedRealityToolKit.cs を介して、シーンと結び付けることで挙動の変更を行います。

今回は DefaultMixedRealityToolkitCongifurationProfile を選択します。

この操作を行なうと開いているシーンのヒエラルキーが以下のように変更されると思います。

このシーンにMRTKが提供しているボタンのプレハブをシーンに設置します。

Projectで「Button」と検索すると、同名のプレハブが見つかると思うのでそれをシーンに持ってきます。

ボタンにイベントを登録

ボタンにイベントを登録したいと思います。

まずは以下のようなテキストに更新を行なうスクリプトを用意して、ボタンにアタッチします。

using UnityEngine;
public class MyScript : MonoBehaviour
{
    private int _count;
    [SerializeField] private TextMesh _label;
    
    public void OnClick()
    {
        _label.text = $"{nameof(MyScript)} : {++_count}";
    }
}

その後、Interactable.cs のイベントに MyScript.OnClick を登録します。

これでアプリは完成です。

UnityEditorで実行

UnityEditorで動かしてみましょう。

このようにMRTKが指の操作をエミュレートしてくれて、ボタンを押したときにログが出力されているのがわかります。

XRデバイスで実行

次にこのアプリを実機ビルドしたいと思います。

MRTKを駆使して作ったアプリなので様々なXRデバイスでそのまま動いてほしいところです。

Hololens

Vive, OculusRiftCV1 (OpenVR)

こちらも無事動きました。やったことはOpenVRのSDKをXRSettingで追加したぐらいです。

Android, iOS (ARFoundation)

こちらも無事動きました。ARはデフォルトのサポートに含まれていなかったので、いくつかの追加対応を行う必要がありました。

対応を行ったのは以下のポイントです。

  • カメラ設定
  • タップイベントの取得部分

カメラには以下のように変更を加えます。

  1. PackageManagerから ARFoundation, ARCoreXRPlugin, ARKitXRPlugin をインポート
  2. 今まで使っていたMainCamera をDisableに変更
  3. GameObject/XR/ARSession, ARSessionOrigin を選択し、シーンに ARCamera, ARSession を配置
  4. ARCameraMixedRealityPlayspace の下階層に移動
  5. MainCamera に含まれるコンポーネントを ARCamera にコピー

最終的には以下のようになっていれば大丈夫です。

ARFoundationのカメラをインポートして、そのカメラにMRTKの設定を追加したという流れになります。

タップイベントの取得は以下のように変更を加えます。

  1. Buttonに PointerHandler コンポーネントをアタッチ
  2. 同コンポーネントの OnPointUpMyScript.OnClick を登録

最終的には以下のようになっていれば大丈夫です。

スクリーンのタップイベントは IMixedRealityPointerHandler を実装しているクラスのみが受け取れるイベントとなっています。

しかし、Interactable はこのインターフェイスを実装していないため PointerHandler を追加でアタッチする必要がありました。

ある操作がどのようなイベントを発行するかは各種コントローラーのクラスを追うことで確認できます。

また、以下のようなスクリプトをシーンに配置して想定するイベントが実際に発行されているのか確認してみるのもよいかと思います。

using Microsoft.MixedReality.Toolkit.Input;
using UnityEngine;

public class MyLogger : InputSystemGlobalHandlerListener, IMixedRealityPointerHandler
{
    protected override void RegisterHandlers()
    {
        InputSystem?.RegisterHandler<IMixedRealityPointerHandler>(this);
    }

    protected override void UnregisterHandlers()
    {
        InputSystem?.UnregisterHandler<IMixedRealityPointerHandler>(this);
    }
    
    public void OnPointerDown(MixedRealityPointerEventData eventData)
    {
        Debug.Log($"{nameof(OnPointerDown)} : {eventData.MixedRealityInputAction.Description}");
    }

    public void OnPointerDragged(MixedRealityPointerEventData eventData)
    {
        Debug.Log($"{nameof(OnPointerDragged)} : {eventData.MixedRealityInputAction.Description}");
    }

    public void OnPointerUp(MixedRealityPointerEventData eventData)
    {
        Debug.Log($"{nameof(OnPointerUp)} : {eventData.MixedRealityInputAction.Description}");
    }

    public void OnPointerClicked(MixedRealityPointerEventData eventData)
    {
        Debug.Log($"{nameof(OnPointerClicked)} : {eventData.MixedRealityInputAction.Description}");
    }
}

※ v2.0.0ではプラットフォームをAndroidにするとエディタでのみMRTKStandardShaderが上手く動作せずピンクになってしまいます。これは以下の方法で抑制することができるようです。

  • グラフィックスAPIのエミュレーションを無効にする(Edit->Graphics Emulation->No Emulation)
  • シェーダーの以下の部分をコメントアウトする
#if defined(SHADER_API_D3D11)
#pragma target 5.0
#endif

https://github.com/microsoft/MixedRealityToolkit-Unity/issues/2517

おわりに

今回はMRTKを簡単に使ってみるという内容でした。

個人的には単純なアプリとはいえ、XRデバイス間の移植がわずかな手間で行えたことにとても手応えを感じました。

MRTKにはまだまだ便利な機能や抽象化のための工夫が揃っており、今後また新たな情報を共有できればと思います。