仮想と物理とエトセトラ

xRや物理とかごった煮の備忘録的技術ブログ

HoloLens2用アプリに再ビルド不要なデバッグモードを追加する(プロトコルでの実装)

今回は小技です。
前回、プロトコルから設定することでHoloLens2用アプリケーションでも起動時のモードを切り替えることができることがわかりました。

xr-physics-work-etc.hatenablog.com

今回はこのプロトコルで設定できるURIスキームを用いて、通常起動では実行されないデバッグモードを用意してみます。

URIスキームを用いたアプリケーションランチャーを作る

前回の記事で、新しいHoloLens2のOSではブラウザからURIスキーマを用いたアプリケーションの起動が行えませんでした。
そのため、まずはURIスキームを用いてアプリケーションを起動できる簡単なHoloLens2アプリケーションを作成します。

今回はシンプルにMRTK導入後、InputFiledとボタンだけで構成しました。 f:id:napo909:20210809161727p:plain

次にURIからアプリケーションを起動するためのスクリプトを作成します。

  • LaunchApp.cs
クリックで展開
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.WSA;

using TMPro;

public class LaunchApp : MonoBehaviour
{
    /// <summary>
    /// 実行するURIスキーム
    /// </summary>
    private string uriScheme = "";
    
    /// <summary>
    /// 入力対象のInput field
    /// </summary>
    [SerializeField]
    private TMP_InputField inputFiled;

    /// <summary>
    /// URIスキームを設定する関数
    /// </summary>
    public void SetScheme()
    {
        uriScheme = inputFiled.text;
    }

    /// <summary>
    /// URIスキームを元に実行する
    /// </summary>
    public void LaunchApplication()
    {
        try
        {
            Debug.Log($"Launch {uriScheme}");
            Launcher.LaunchUri(uriScheme, true);
        }
        catch (System.Exception e)
        {
            Debug.Log(e);
        }
    }
    
}

作成したスクリプトコンポーネントとしてアタッチし、コンポーネントにInputFieldを参照させます。
f:id:napo909:20210809162149p:plain

また、InputFiledにURIスキームの設定(SetScheme)を、ボタンにURIスキームを元としたアプリケーションの実行(LaunchApplication)を設定します。
f:id:napo909:20210809181016p:plain

f:id:napo909:20210809163036p:plain

これで、InputFieldに入力したURIからアプリケーションを起動できるようになりました。

プロトコルデバッグモードを実装する

次に、デバッグモード仕込むアプリケーションを作成します。
今回はアプリ名をURISchemeTestにしています。
このアプリケーションがアプリケーションランチャーから起動されるものです。
MRTKを導入後、以下のようなHierarchyでシーンを設定します。
デバッグモードでない場合にも何か表示させるために、Cubeも配置しています。
f:id:napo909:20210809173254p:plain

デバッグモード用に、デバッグモードである旨を示すテキストとして、Debug Mode(TextMeshPro)、デバッグログ表示のためLogger(TextMeshPro)を用意しています。
今回は、Logger(TextMeshPro)でのログ出力にホロモンさんの下記を使用しました。

bluebirdofoz.hatenablog.com

次に、URIを解釈し、必要があればデバッグモードに遷移するためのスクリプトを作成します。
今回は?区切りでDebugの文字列がURI中にある場合はデバッグモードとして扱うようにしました。

  • DebugControlManager.cs
クリックで展開
using UnityEngine;
using Microsoft.MixedReality.Toolkit;
public class DebugControlManager : MonoBehaviour
{
    /// <summary>
    /// 自インスタンス
    /// </summary>
    private static DebugControlManager instance;

    /// <summary>
    /// デバッグモードでのみ表示するオブジェクト
    /// </summary>
    [SerializeField]
    private GameObject[] targetObjects;

    /// <summary>
    /// デバッグモードかどうか
    /// </summary>    
    public bool isDebugMode = false;

    /// <summary>
    /// デバッグモードにする場合のコマンドキーワード
    /// </summary>
    private static string debugKeyword = "Debug";

    void Awake()
    {
        // シングルトン化
        if (instance == null)
        {
            // 未作成の場合作成
            instance = this;
            DontDestroyOnLoad(this.gameObject);
        }
        else
        {
            // すでに作成されている場合削除
            Destroy(this.gameObject);
        }
    }

    // Start is called before the first frame update
    void Start()
    {
        Debug.Log("Start Check URI Schema");
        Debug.Log($"URI:{Application.absoluteURL}");

        // カスタム URI スキームを使用してアプリケーションが起動されている場合、
        // Application.absoluteURLに値が入る
        if (!string.IsNullOrEmpty(Application.absoluteURL))
        {

            GetURIInfo(Application.absoluteURL);
        }
        SetDebugState();
    }

    // Update is called once per frame
    void Update()
    {

    }

    /// <summary>
    /// URI情報取得処理
    /// </summary>
    /// <param name="uri"></param>
    void GetURIInfo(string uri)
    {
        string[] command;

        try
        {
            command = uri.Split('?');
        }
        catch (System.Exception e)
        {
            Debug.Log(e);
            return;
        }

        DecodeURICommand(command);


    }

    /// <summary>
    /// URIコマンド解釈処理
    /// </summary>
    /// <param name="args"></param>
    void DecodeURICommand(string[] args)
    {
        isDebugMode = false;

        foreach (var arg in args)
        {
            if (arg == debugKeyword)
            {
                Debug.Log("Exists debug command");
                isDebugMode = true;
            }
        }

    }

    /// <summary>
    /// デバッグ状態の設定処理
    /// </summary>
    void SetDebugState()
    {
        foreach (GameObject targetObject in targetObjects)
        {
            // 対象オブジェクトの有効/無効化
            targetObject.SetActive(isDebugMode);
        }

        // MRTKの診断の有効/無効化
        MixedRealityToolkit.DiagnosticsSystem.ShowDiagnostics = isDebugMode;


    }
}

作成したDebugControlManagerを適当なオブジェクトにアタッチして、デバッグモードでのみ表示したいオブジェクトを設定します。
f:id:napo909:20210809175552p:plain

次に、URIスキームを使用するために必要な、プロトコルの設定を行います。
PlayerSettingPlayerPublishing SettingsのProtocolにURIスキーマとして設定するためのキーワードを設定します。
今回はuri-scheme-testを設定しました。
f:id:napo909:20210809171138p:plain

これでURIスキームを使用するための設定ができました。
UnityアプリケーションをUWP用にビルドしてできたVisual StudioのソリューションファイルからPackage.appxmanifestを確認すると、プロトコルの設定が正しくされていることを確認できます。
f:id:napo909:20210809175716p:plain

動作確認

動作確認として3パターン試してみます。

1. いつもアプリケーションを実行する場合と同じようにURISchemeTestを実行する

こちらはメニューからのいつも通りの起動のため、結果のみ記載すると、

[結果]

  • 赤いCubeのみ表示される。
  • MRTK標準の診断は表示されない。

f:id:napo909:20210809174445j:plain

2. アプリケーションランチャーから起動する

今回設定したURIスキームをアプリケーションランチャーに設定して起動します。
特に設定値はないので、適当に入力します。
uri-scheme-test://hoge?hoge

[結果]

  • URIスキームに対応するアプリケーション(今回の場合はURISchemeTest)が実行される
  • デバッグオプションを付与していないので、それ以外は1.と同じ

f:id:napo909:20210809174535j:plainf:id:napo909:20210809174543j:plain

3. URIデバッグオプションを加えてアプリケーションランチャーから起動する

次にURIデバッグオプションを追加して実行します。
uri-scheme-test://hoge?hoge?Debug

[結果]

  • URIスキームに対応するアプリケーション(今回の場合はURISchemeTest)が実行される
  • デバッグモードでのみ表示設定したDebug Modeの文字列とデバッグログが表示される
  • (スクリーンショットに映っていないが)MRTKの診断が表示される

f:id:napo909:20210809174640j:plainf:id:napo909:20210809174651j:plain

これで、プロトコルURIスキーム)を用いたデバッグモードを仕込むことができました。
再ビルドしなくても、通常起動と、デバッグモードをHoloLens2のみで切り替えることができます。
他にも、アプリケーションへの引数の渡し方として応用できるような気がします。