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