Our game includes an in-game level editor. When the user saves a custom level, the level is serialized and written to a file:
public void SaveFile<T>(T obj, string path) {
if (!typeof(T).IsSerializable) {
throw new ArgumentException("Tried to save non-serializable type " + typeof(T).Name);
}
FileStream fs = null;
try {
fs = new FileStream(path, FileMode.Create);
DataContractJsonSerializer serializer = GetSerializer();
serializer.WriteObject(fs, obj);
} catch (Exception ex) {
Debug.LogException(ex);
} finally {
if (fs != null) fs.Close();
}
}
Serialized files can be loaded like this:
public T LoadFile<T>(string path) {
if (!typeof(T).IsSerializable) {
throw new ArgumentException("Tried to deserialize non-serializable type " + typeof(T).Name);
}
if (!File.Exists(path)) return default(T);
FileStream fs = null;
T result;
try {
fs = new FileStream(path, FileMode.Open);
DataContractJsonSerializer serializer = GetSerializer();
var result = (T)serializer.ReadObject(fs);
} catch (Exception ex) {
Debug.LogException(ex);
throw ex;
} finally {
if (fs != null) fs.Close();
}
return result;
}
When displaying a "Load" menu, we enumerate the saved files like this:
public List<T> LoadFiles() {
if (!Directory.Exists(path)) {
Debug.Log("No save files found");
return new List<T>();
}
var files = Directory.EnumerateFiles(path);
Debug.Log("Found " + files.Count() + " files");
List<T> result = new List<T>(files.Count());
foreach (string file in files) {
Debug.Log(file);
T obj = LoadFile<T>(file);
if (obj == null) Debug.Log("File at " + file + " loaded null");
if (obj != null) result.Add(obj);
}
return result;
}
I have omitted a lot of code for brevity, but what is shown above should cover the important parts.
In the Editor, everything works perfectly. However, in WebGL builds (where files are saved to/loaded from the browser IndexedDB), there is a strange quirk: the file doesn't remain in IndexedDB unless the user changes to a different scene after saving.
Scenario 1:
- In the level Editor, Bob presses "Save"
- The file is saved, and the browser console shows the log entry
File saved to /idbfs/abc123/CustomLevels//FileName
- Bob refreshes the webpage
- Bob clicks "Load"
- The game searches IndexedDB but does not find the file saved in step 2
Scenario 2:
- In the level Editor, Alice presses "Save"
- The file is saved, and the browser console shows the log entry
File saved to /idbfs/abc123/CustomLevels//FileName
- Alice returns to the main menu scene
- Alice refreshes the webpage
- Alice clicks "Load"
- The game searches IndexedDB and does find the file saved in step 2
The browser console log suggests that after Bob refreshes the page in Scenario 1, the file no longer exists. If this was the only scenario that Bob had saved, we see the message "No save files found". If Bob had previously saved other scenarios and used the workaround of returning to the main menu scene, those previously saved files will appear in the console and save list, but the most recent file is missing.
Why would the save file disappear from the IndexedDB if the user leaves the webpage without changing scenes, but remain in the IndexedDB if the user returns to the main menu scene before leaving the webpage?