1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【WebGL】ファイル操作の同期ネイティブコード

Last updated at Posted at 2025-05-22

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 the Application.persistentDataPath directory by calling the JS_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() は非推奨になったらしいので、注意。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?