Arrival in Hell Dev Blog #7 – Saving and Loading

I took a break from these posts for the holidays, so I thought we’d jump right back in with quite a code-heavy one! I’ll be summarizing how the save/load system works in Arrival in Hell.

The first thing I needed to do was make commonly used ‘complex’ object serializable (you’ll see why later). So I made a couple of little classes for Quaternion and Vector3 since both are used extensively in the game.


public class Vector3Serializable
	public float x;
	public float y;
	public float z;
	public Vector3Serializable(Vector3 vector3) {
		x = vector3.x;
		y = vector3.y;
		z = vector3.z;
	public Vector3 toVector3() {
		return new Vector3(x, y, z);

public class QuaternionSerializable
	public float x;
	public float y;
	public float z;
	public float w;
	public QuaternionSerializable(Quaternion quaternion) {
		x = quaternion.x;
		y = quaternion.y;
		z = quaternion.z;
		w = quaternion.w;
	public Quaternion toQuaternion() {
		return new Quaternion(x, y, z, w);


These classes allow me to quickly convert to and from a serializable and non-serializable version of the same data. I also did this for my custom type InventoryItem; it is the only custom complex type I use.

Next I needed to create a SaveData object (also serializable) which can store the entire state of the game. This includes player position, player rotation, flags (turned on and off as you interact with IneractiveObjects), positions and rotations of every Interactive Object, the current InventoryItems in your inventory and finally a snapshot of where you are with any dialogue trees (unlocked conversations etc).

public class SaveData
public Vector3Serializable playerPosition;
public QuaternionSerializable playerRotation;

public Dictionary<string, bool> flags;
public Dictionary<string, Vector3Serializable> positions;
public Dictionary<string, QuaternionSerializable> rotations;

public List<InventoryItemSerializable> inventory;
public string dialogue;

Whenever you hit save, the first step is to populate this object. Here is how I went it for each property:

  1. Player position and rotation are pretty straight forward, only thing to remember is to convert to the serializable objects since Vector3 and Quaternion are not serializable
  2. Flags are already contained in a Dictionary object with Bool values and String keys, so this is already serializable and can just be copied over to the save object
  3. When the game starts, all interactive objects register themselves with the save system. Every time you save the game, the interactive objects are looped through, and their position and rotation recorded in serializable objects
  4. Inventory is looped through and items stored as serializable objects
  5. The excellent Dialogue system we are using actually has a method for outputting it’s state as a String which can later be read back; simply call PersistentDataManager.GetSaveData()

So now we have a complete save game object, the next step is to convert the object to a save-able format, then save that to disk. These 4 lines of code do the job:


BinaryFormatter bf = new BinaryFormatter ();
FileStream file = File.Create (path);

bf.Serialize (file, data);
file.Close ();

For more detail on how all of this works check out the Unity documentation as well as this great tutorial.

In order to load we simply do the reverse. Load the file from the system, parse it into a SaveData object, then take those data objects and write them to the correct places instead of reading. In order to have multiple save game files, I simply use a different filename for each of the 6 save ‘slots’ available in the game

One last thing worth mentioning is that with each save game I take a screenshot with every save to be displayed as a thumbnail for each save file. The best way I found to do this without a big lag spike was to read the pixels on screen, scale them down, and then save it. I also do it in a Coroutine which waits for the end of the frame after a close, otherwise all the thumbnails are just a screenshot of the save menu!

IEnumerator TakeScreenshot(int slot)
   yield return new WaitForEndOfFrame();

   Texture2D texture = new Texture2D(Screen.width, Screen.height, TextureFormat.RGB24, false);
   texture.ReadPixels(new Rect(0, 0, Screen.width, Screen.height), 0, 0);
   TextureScale.Bilinear(texture, (int)ThumbSize.x, (int)ThumbSize.y);
   System.IO.File.WriteAllBytes(Application.persistentDataPath + "/saveGame" + slot + ".png", texture.EncodeToPNG());

   if (saveSlots[slot])
The finished load screen

The finished load screen

So there it is. It’s very simple and requires a lot of manual data pulling and pushing, but it works fine for this game. If I had to do it again perhaps I’d create a ‘Saveable’ component which can be attached to any game object, which would automate the process slightly.

Next week I’ll talk about the image effects I’m using.

Share This:

One thought on “Arrival in Hell Dev Blog #7 – Saving and Loading

  1. Pingback: Arrival in Hell Dev Blog #9 – Optimisation – Epic Industries

Leave a Reply

Your email address will not be published. Required fields are marked *