[UPDATE]
Unity Save Load Utility, the successor to SerializeHelper, has been uploaded. An new thread has been created on the Unity forums:
[/UPDATE]
So, saving & loading player progress is something that most games need in some form or another, and often, the PlayerPrefs way of doing it is not sufficient. The late and great UnitySerializer is no longer supported and was always something of a monster in terms of complexity, so I made my own system for saving and loading objects in the scene.
So, what is it, and what can it do?
Currently, it is a small collection of simple scripts and classes that allow you to save and load GameObjects by serializeing and writing them to a savegame file via BinaryFormatter. So far, only a GO’s transform, active state, name, and any MonoBehavior scripts on it are saved, along with their variable values, of course. That means that you will have to create your own workarounds for saving and loading things like Renderers and other components. I did not include them because their importance varies from project from project.
How do you use it?
Simple: Open the provided sample scene, and either hit Escape or F5 and F9 on your keyboard for the menu or QuickLoad and QuickSave, respectively. Note that a save game file and possible directory structure will be created on your hard disk. Take a look at the “SaveLoadMenu” script to see where files are saved.
How it works, in simple words:
At the core lies the SaveGame class. an instance of this class is created when we want to save. This class holds a list of instances of the class SceneObject.
SceneObject in turn represents a GameObject in a form that can be serialized. It holds a GO’s name, id, parent’s id (if any), Transform values (rot/pos/scale), active state, and a list of instances of the class ObjectComponent.
ObjectComponent represents one MonoBehavior (currently) component (“script”). It holds the component’s name as a string, and a Dictionary<string,object> “fields”. This dictionary holds a field’s name as key and a field’s value as value, stored as an object.
Each GameObject that should be able to be saved and loaded needs two things:
- A component “ObjectIdentifier”
- A Prefab of it somewhere in the Resources folder, which of course also needs an ObjectIdentifier component.
ObjectIdentifier is a MonoBehavior component that holds a GameObject’s prefab name and id and parent’s id values.
If we want to save the GameObject in our scene, the following happens:
(0.) At runtime start, the prefabDictionary is filled. This collection holds references to all GameObjects in the Resources folder which have an ObjectIdentifier component. This dictionary is later used to reconstruct a GameObject.
- A new instance of SaveGame is created
- All occurences of the ObjectIdentifier is collected, thereby creating a collection of GameObject that should be saved.
- For each GO, a new instance of SceneObject is created. This gets “filled” by “packing” the GameObject’s components into serializable form, and copying the ids, Transform, and other misc. data.
- Each SceneObject instance created for a GO is added to the SaveGame’s list of SceneObjects.
- The SaveGame is serialized by the static function SaveLoad/Save method and written to a file in the hard disk. ISerializationSurrogates are used to serialize Unity-specific types like Vector3 (a few examples are provided)
If we want to load a saved game, the following happens:
- All Objects which are not tagged as “DontDestroy” (persistent objects, like managers etc.) are destroyed, thereby clearing the scene and creating a blank slate.
- The SaveGame instance is deserialized from file
- Each SceneObject in the SaveGame instance’s list of SceneObjects is “unpacked”; A SceneObject’s prefabName value is used to pull a prefab from a the prefabDictionary and instantiate a copy of it.
- The newly instantiated GO’s components and misc. values are reconstructed from the data stored in the SceneObject instance.
I want to stress the fact that while it has been tested, it represents a bare-bones aproach and should be considered a stepping stone on the way to implement your own save/load feature in your project. This package has been kept simple on purpose, both because it should be easy to understand and also because each project is different in it’s needs.
It’s also worth noting that serialization is, at least by me, considered an advanced topic which requires copious amounts of research and trial and error in order to understand it. I recommend the Microsoft Developer Network (MSDN) and StackOverflow.com for further information.
Before using the assets, I strongly recommend at least cursory reading of all the scripts. I included numerous comments and some readme files. You absolutely HAVE to get a basic understanding of what happens
SerializeHelper Download Link
(Alternate download from my own webspace: SerializeHelper Download Link)
(Project folder from my own webspace, in case the asset package doesn’t work: SerializeHelper Project Folder)