Unityドキュメントより
問題: Application.persistentDataPath に保存したファイルが永続化されない
Unity WebGL は、セッション間で永続化させる必要のあるすべてのファイル (PlayerPrefs や persistentDataPath に保存されるファイルなど) をブラウザー IndexedDB に保存します。これは非同期 API なので、いつ終了するか分かりません。
以下のコードを呼び出して、メモリから IndexedDB ファイルシステムへの、持続中のファイルシステムの書き込み操作をすべてフラッシュするようにします。
FS.syncfs(false, function (err) { if (err) { console.log("Error: syncfs failed!"); } });
上記の記載はUnity2022.3までのリファレンスだとあるのに(若干少しずつ記述が更新されていたが)、Unity6000以降は同じページが見つからない。
ただ、Unity6000.2だと
Property Use autoSyncPersistentDataPath: true
If set to true, all file writes inside the Unity Application.persistentDataPath
directory automatically persist so that the contents are remembered when the user revisits the website the next time. If unset (or set to false), you must manually sync file modifications inside theApplication.persistentDataPath
directory by calling theJS_FileSystem_Sync()
JavaScript function.
という記載があり、「わざわざネイティブコードで呼ばなくても自動的に同期してくれる設定もできたけど、使用しないのであれば依然としてこれまでと同じく JS_FileSystem_Sync()
呼んでくれてもいいよ」(意訳)と書いてあるように思う。
ということで、次節で書き残すコードは今後も無価値無意味ではなさそう。
単純に、自分の実装では使い道がなくなっただけなので、ここで供養(≒アウトプット)しておく。
同期コード
デリゲート地獄だけどやむなし。
idbfs.jslib
mergeInto(LibraryManager.library, {
SyncFS: function (callback) {
FS.syncfs(false, function (err) {
if (err){
var buffer = stringToNewUTF8(err.message);
{{{ makeDynCall('vii', 'callback') }}} (false, buffer);
_free(buffer);
} else {
{{{ makeDynCall('vii', 'callback') }}} (true, null);
}
});
},
});
NativePluginsBridge.cs
using System;
using System.Runtime.InteropServices;
using AOT;
using UnityEngine;
namespace DefaultNameSpace
{
public static class NativePluginBridge
{
public static event Action OnSyncFSCompleted;
[DllImport("__Internal")]
private static extern void SyncFS(Action<bool, string> callback);
[MonoPInvokeCallback(typeof(Action<bool, string>))]
private static void SyncCall(bool success, string message)
{
if (success)
{
OnSyncFSCompleted?.Invoke();
}
else
{
Debug.LogError("SyncFS failed: " + message);
}
}
public static void SyncFS() => SyncFS(SyncCall);
}
}
追伸
いつの間にやら、dynCall()
は非推奨になったらしいので、注意。