I have 9 Prefabs, each with the ES3 Prefab Script and one child Cube. Each child cube has a Mesh Filter, Mesh Renderer, Box Collider, Rigidbody. I've tried this experiment both with those children having and not having the ES3 Prefab script attached. (Should it be attached or no?) The child cubes all have the Tag "Pillar".
Saving to and loading from a file works fine during a single game session, but if I stop the game then start it back up before loading, when I load some of the cubes disappear due to having their Mesh Filter changed from Cube to None. Other cubes do not disappear, but do have "Easy Save 3 Loaded GameObject" siblings appear in the hierarchy for some reason. These new siblings have a Mesh Filter with no mesh, a Mesh Renderer, and Box Collider, but for whatever reason no Rigidbody. There are always 5 cubes which get these siblings, and it is always the same 5.
Clicking on one of these siblings shows ES3 Inspector Info "This GameObject was created because Easy Save could not find a GameObject in the scene with the same instance ID as the GameObject the Component we are loading is attached to. To prevent this from being created, use the LoadInto methods to tell Easy Save what Component the data should be loaded into."
The thing is, I am using LoadInto. Here's the code (note that I am not testing the LoadFromCache method, only the LoadFromFile method):
Code: Select all
using System.IO;
using System.Linq;
using UnityEngine;
public interface ITaskable {};
public class SaveSystem : MonoBehaviour, ITaskable {
static ES3File _es3;
static string _path;
static GameObject[] gameState;
// Initialize the save cache.
public void Start() {
// Set the file path (this is ES3's default path, aka ES3Settings.directory).
_path = Application.persistentDataPath + "/Saves/";
// Get reference to the game state.
// (For now, we are just tracking the pillars.)
gameState = GameObject.FindGameObjectsWithTag("Pillar");
// Create a new temporary save cache.
_es3 = new ES3File("temp.es3");
}
// Retrieve save files, sorted by date/time.
static IOrderedEnumerable<FileInfo> GetSaveFiles() => new DirectoryInfo(@_path).GetFiles("*.es3").OrderByDescending(x => x.LastWriteTime);
// Save the game state to memory and file.
public static void Save() {
SaveToCache();
SaveCacheToFile();
}
// Save the game state to memory.
public static void SaveToCache() => _es3.Save<GameObject[]>("gameState", gameState);
// Commit the save cache to the file system.
public static void SaveCacheToFile() {
// Create the Saves folder if it does not exist.
System.IO.Directory.CreateDirectory(_path);
int maxSaves = 3;
// Name file with date.
string filename = $"Saves/{System.DateTime.Now:yyyy-MM-dd_hh-mm-ss-tt}.es3";
// Write the cache to file.
_es3.Sync(filename);
// Delete any save files after maxSaves.
int i = 1;
foreach (FileInfo file in GetSaveFiles()) {
if (i > maxSaves) {
file.Delete();
}
i++;
}
}
// Load the save cache into the game.
public static void LoadFromCache() => _es3.LoadInto<GameObject[]>("gameState", gameState);
// Load the most recent save file.
public static void LoadFromFile() {
// Get the most recent save file.
FileInfo file = GetSaveFiles().FirstOrDefault();
// Bail if there are no save files.
if (file == null) {
return;
}
// Load the file into the game.
ES3.LoadInto<GameObject[]>("gameState", file.ToString(), gameState);
// Commit the current state into the save cache.
SaveToCache();
}
}