UnityStandaloneFileBrowserを使ってみた
Unityでファイル選択ダイアログを使う必要があり、方法を調べていたところ以下2つの方法が見つかりました。(他にもあるかもしれませんが、筆者が調べた範囲で見つかったものは以下でした)
OpenFileDialogは.NETのクラスなので、Windowsビルド向けにしか利用できない模様。今回は、WebGLビルドで利用したかったため、UnityStandaloneFileBrowserを試すことにしました。
UnityStandaloneFileBrowserは、各OS(Windows,Mac,Linux )ビルド、WebGLビルドに対応しているようです。
サンプルアプリの作成
本記事執筆時における環境情報は以下です。
- OS:
macOS Monterey バージョン12.5.1 - Unity Editor:
バージョン2021.3.5f
なお、今回作成したサンプルアプリは以下に置いています。
UnityStandaloneFileBrowserの導入
-
UnityStandaloneFileBrowserのGithubページのDownload Packageより、StandaloneFileBrowser.unitypackageをダウンロードします。 -
ダウンロードした
StandaloneFileBrowser.unitypackageをUnityプロジェクトのプロジェクトウィンドウのドラッグ&ドロップして、インポートします。

コンソールにエラーが出てましたが、一旦無視します。

GameObjectの配置
Canvasとその下にPanelを作成。さらにその下にLoadとSaveのボタン、テキスト出力用のテキストを作成しています。配置は適当です。

スクリプト作成
Assetsフォルダの下にScriptsフォルダを作成。
Scripts配下に、FileLoadSample.csとFileSaveSample.csの2つのファイルを作成します。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using SFB;
using System.IO;
using System.Text;
using System.Runtime.InteropServices;
using UnityEngine.Networking;
using UnityEngine.UI;
using UnityEngine.EventSystems;
[RequireComponent(typeof(Button))]
public class FileLoadSample : MonoBehaviour, IPointerDownHandler
{
// テキストアウトプット
[SerializeField] private Text outputText;
// 読み込んだテキスト
private string _loadedText = "";
#if UNITY_WEBGL && !UNITY_EDITOR
//
// WebGL
//
// StandaloneFileBrowserのブラウザスクリプトプラグインから呼び出す
[DllImport("__Internal")]
private static extern void UploadFile(string gameObjectName, string methodName, string filter, bool multiple);
// ファイルを開く
public void OnPointerDown(PointerEventData eventData) {
UploadFile(gameObject.name, "OnFileUpload", ".", false);
}
// ファイルアップロード後の処理
public void OnFileUpload(string url) {
StartCoroutine(Load(url));
}
#else
//
// OSビルド & Unity editor上
//
public void OnPointerDown(PointerEventData eventData) { }
void Start()
{
var button = GetComponent<Button>();
button.onClick.AddListener(() => OpenFile());
}
// ファイルを開く
public void OpenFile()
{
// 拡張子フィルタ
var extensions = new[] {
new ExtensionFilter("All Files", "*" ),
};
// ファイルダイアログを開く
var paths = StandaloneFileBrowser.OpenFilePanel("Open File", "", extensions, false);
if (paths.Length > 0 && paths[0].Length > 0)
{
StartCoroutine(Load(new System.Uri(paths[0]).AbsoluteUri));
}
}
#endif
// ファイル読み込み
private IEnumerator Load(string url)
{
var request = UnityWebRequest.Get(url);
var operation = request.SendWebRequest();
while (!operation.isDone)
{
yield return null;
}
_loadedText = request.downloadHandler.text;
Debug.Log(_loadedText);
outputText.text = _loadedText;
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using SFB;
using System.IO;
using System.Text;
using System.Runtime.InteropServices;
using UnityEngine.Networking;
using UnityEngine.UI;
using UnityEngine.EventSystems;
[RequireComponent(typeof(Button))]
public class FileSaveSample : MonoBehaviour, IPointerDownHandler
{
// テキストアウトプット
[SerializeField] private Text outputText;
#if UNITY_WEBGL && !UNITY_EDITOR
//
// WebGL
//
// StandaloneFileBrowserのブラウザスクリプトプラグインから呼び出す
[DllImport("__Internal")]
private static extern void DownloadFile(string gameObjectName, string methodName, string filename, byte[] byteArray, int byteArraySize);
// ファイルを保存する
public void OnPointerDown(PointerEventData eventData) {
var str = outputText.text + "_saved";
if (str.Length > 0)
{
var bytes = Encoding.UTF8.GetBytes(str);
DownloadFile(gameObject.name, "OnFileDownload", "sample_saved.txt", bytes, bytes.Length);
}
}
// ファイルダウンロード後の処理
public void OnFileDownload() {
Debug.Log("CSV file saved");
outputText.text = "File Saved";
}
#else
//
// OSビルド & Unity editor上
//
public void OnPointerDown(PointerEventData eventData) { }
void Start()
{
var button = GetComponent<Button>();
button.onClick.AddListener(() => SaveFile());
}
// ファイルを保存する
public void SaveFile()
{
var str = outputText.text + "_saved";
if (str.Length > 0)
{
var path = StandaloneFileBrowser.SaveFilePanel("ファイルの保存", "", "sample_saved", "txt");
if (!string.IsNullOrEmpty(path))
{
File.WriteAllText(path, str);
Debug.Log("File saved");
outputText.text = "File Saved";
}
}
}
#endif
}
FileLoadSample.csはLoadButtonに、FileSaveSample.csはSaveButtonにアタッチします。インスペクタビューより、Outputテキストへの参照を渡します。


エディタ上でデバッグ実行してみます。
まずはロードです。Loadボタンを押すと、ファイル選択ダイアログが開きます。

ファイルを開くと、色々エラーは出たままですが、とりあえず出力用テキストとコンソールにファイル内容が出力されます。


次にセーブです。Saveボタンを押すと、ファイル保存のダイアログが開きます。

保存されたファイルを開くと、先ほど開いたファイル内容に_savedが追記されて保存されました。

WebGLビルド
[Build Settings...]→[WebGL]を開き、Switch Platformをクリックします。

しばらく待つと完了しますが、Buildが押せない状態になっています。

[Player Settings]を開き、[Player]→[Other Settings]を確認すると、Color SpaceとLightmap Encodingに注意書きが出ています。

それぞれ、GammaとNormal Qualityに変更します。

ビルドができるようになったので、Build And Runをクリックします。
保存先は適当に指定。ビルドには数分かかります。

動作確認
ビルドが終わると、ブラウザが自動的に開きます。
ボタンサイズがかなり小さくなってしまいましたが。。とりあえず起動しました。

WebGL後も、Loadボタンを押すと問題なくファイル選択ダイアログが開きます。

Saveボタンも問題ありませんでした。

以上、UnityStandaloneFileBrowserを使ってファイル選択ダイアログを利用することができました。
細かい挙動についてはまだ理解しきれていないので、色々試しながら理解していきたいところです。
Discussion