Menu

22 Oct 2015

Saving and Loading Files in Unity

So, it's been a while since I've made a post on here and I've actually got a number of topics I'd like to make posts about.

A while back I was working on a simple Unity project that needed the ability to save and load highscore data. The most common solution I've found other developers implement is to create and manage a set of PlayerPrefs keys in their projects. For me, I like having a custom external file that I can access with other C# utilities should I want to inspect and compare the contents of save files during development. With that in mind, here is a simple serialization script for Unity and a very simple project to demonstrate how it works.

The Project

I've created a simple project in Unity with 2D format. In the scene is a Cube, three buttons, a point light, and a pair of scripts. One script is used to manage the colour of the cube and the other is the SaveLoadBehaviour script which will handle our "game data":

Hierarchy for the scene
I've also created a specular material to put on the cube so that it reflects the colour changes as we make them in runtime.

Both scripts - SaveLoadBehaviour and ColourBehaviour - are attached to the Cube object out of convenience. The buttons each call SendMessage on ColourBehaviour, each sending the string "Red", "Green", or "Blue" as appropriate.

The ColourBehaviour script is relatively simple:

The Start method checks for a save file to set the cube colour, defaulting to red
When the scene loads the ColourBehaviour script calls the SaveLoadBehaviour to check if there's a file already in existence and if so to load the colour from it. It then calls one of the colour assignment methods:

Colour setting methods - they also call the SaveGameData method
The SaveLoadBehaviour script in this simplistic implementation only features to methods, SaveGameData and LoadGameData. The beauty of using serialization on an object (in this case the GameData object) is that you won't really need anything more complex, as all of the complexity is in the object itself and the methods just cram it into a file.

Speaking of GameData:

GameData is a struct with a string representing the most recent colour of the cube
It's a simple object for storing a string. Again, it's not meant to be truly complex information about a real game, it's just meant to show off saving and loading in this context. One note about the project in this example is that the ColourBehaviour script references the GameData directly from the SaveLoadBehaviour, don't do that in a real game. Responsible coding would have a GameData object in any scripts referencing the save data and would manipulate their own local object before passing it back to the SaveLoadBehaviour script for serialization and storage.

The save and load methods are very simple:

The SaveGameData and LoadGameData methods
These are essentially all the script needs to do its work. The GameData object stores the relevant data, in this case a colour, and the object is serialized and deserialized as necessary. If you play the scene now and click the various buttons, you'll find that the colour value assigned before stopping play will persist on the next play. This is because the SaveLoadBehaviour is currently calling LoadGameData in it's Start method.

It will still be a blue cube when the scene is next played


So that's how vanilla serialization can be used to make save files in Unity. As long as the [Serializable] tag is applied, more complex objects can be handled without any changes to the methods. A github link to the example Unity project is below but please note that accessing the SaveLoadBehaviour's object from the outside is poor practice and that the filepath for saving is currently hardcoded - this is fine for a simple project with just one save file, but for multiple save files there will be some additional functionality required.

Here's the github link: https://github.com/AdamBoyce/UnitySaveLoadExample

I hope this is helpful to someone out there, and thanks for reading.