MRが楽しい

MRやVRについて学習したことを書き残す

HoloLens2でファイルピッカーを使って端末のファイルを参照する

本日はHoloLens2の小ネタ枠です。
HoloLens2でファイルピッカーを使って端末のファイルを参照する方法についてです。

Windows.Storage.Pickers.FileOpenPicker

UWPプラットフォームで利用可能なFileOpenPickerはファイルを選択して開くことができるUIを表示します。
learn.microsoft.com

Unityでファイルピッカーを利用する場合、本関数は以下のようにメインスレッドではなくUIスレッドで実行する必要があります。

UnityEngine.WSA.Application.InvokeOnUIThread(async () =>
{
    var picker = new Windows.Storage.Pickers.FileOpenPicker();
    picker.FileTypeFilter.Add("*");
    var file = await picker.PickSingleFileAsync();
    if (file != null)
    {
        // ファイル処理
    }
}, false);    

サンプルコード

ボタンを押下するとファイルピッカーが開き、ファイルを選択すると選択したファイルの名前を表示するサンプルスクリプトを作成しました。
・FilePickerTest.cs

using System;
using UnityEngine;
using Microsoft.MixedReality.Toolkit.UI;
using TMPro;
using UniRx;

public class FilePickerTest : MonoBehaviour
{
    [SerializeField] private Interactable mrtkButton;

    [SerializeField] private TMP_InputField resultText;
    
    void Start()
    {
        // 起動と同時にボタン押下イベントを登録
        mrtkButton.OnClick.AsObservable().Subscribe(_ =>
        {
#if WINDOWS_UWP
            // UWPプラットフォームではファイルピッカーを起動
            // ファイルピッカーはUIスレッドでのみ動作する
            UnityEngine.WSA.Application.InvokeOnUIThread(async () =>
            {
                var picker = new Windows.Storage.Pickers.FileOpenPicker();
                picker.FileTypeFilter.Add("*");
                var file = await picker.PickSingleFileAsync();
                if (file != null)
                {
                    // 指定されたファイル名を表示
                    //メインスレッドで実行
                    UnityEngine.WSA.Application.InvokeOnAppThread(() =>
                    {
                        resultText.text = file.Name;
                    }, false);
                }
            }, false);            
#endif
        })
        // オブジェクト破棄のタイミングでボタン押下時イベントを解除
        .AddTo(this);
    }
}

サンプルシーンにスクリプトを配置し、ButtonとTextコンポーネントの参照を設定しました。

プロジェクトをUWPプラットフォームでビルドしてアプリをHoloLens2にデプロイします。

HoloLens2上で起動したアプリ内でボタンをタップするとファイルピッカーが開きます。
UIスレッド上で表示されるUIはキャプチャできないようでファイルピッカーの撮影はできませんでした。