Skip to content
This repository was archived by the owner on Jul 21, 2020. It is now read-only.

SGS Savegames a technical overview

damagefilter edited this page Nov 17, 2016 · 1 revision

Here's a quick break-down of how the save system works in general.

First: It's based on protocol buffers wire format. So the save data generated is an array of bytes that can be written to disk (or pushed to a cloud service, whatever). It uses the protobuf-net library written by Marc Gravell

This page describes the default save-game implementation but you can add, change or re-arrange the whole thing to your needs if you want to. In the end it all comes down to that you store any IDataBlock implementaion in a SaveFile.

How Saving works

As the smallest existing unit of save-data there is the IDataBlock. This interface can be implemented to represent any form of data. For describing how the save system stores things, we'll be going with the SceneDataBlock as a base for storing a whole scene state. It contains a list of GameObjectDataBlock objects describing serialized data for a whole GameObject. This, in the end, contains a list of ComponentDataBlock objects which describe the data of each component attached to a GameObject. Each GameObject that is bound to be stored anywhere (in this case in a SceneDataBlock) needs to have a SaveManager component attached. You can save (and restore of course) prefabs, assets from asset bundles or loose gameObjects flying around in your scene.

So generally, the structure is pretty easy to read and understand in code. One DataBlock into another until, in the end, one big datablock is written into a byte stream which is then used to put it these byte wherever you need them.

ComponentDataBlock

This piece of object contains data representing a single component on a GameObject. You decorate your MonoBehavior objects with the SaveableComponentAttribute to signal that it contains data that needs serializing. Fields that need to be serialized must be decorated with the SaveableFieldAttribute, which describes how the data should be serialized. Decorated fields can be of any visibility.

Okay so, after processing there's a list in the ComponentDataBlock that contains information about serialized fields. That is: Their name, their type and their serialized content in byte form.

GameObjectDataBlock

This is simply a container that holds a list of ComponentDataBlock objects. As you will have guessed this is the "main thing" in the whole system. It represents one GameObject in the scene. In case of prefabs it can also represent a prefab to allow storing and restoring complex GameObject structures. We will discuss details about that one at a later time.

SceneDataBlock

And this is the place where all GameObjectDataBlocks are stored in a list. That's all it is.

SaveFile

Now we've come to the end of the format chain. The SaveFile can store any IDataBlock implementation. In the default per-scene setup however, we store a list of SceneDataBlocks keyed by the name of the scene they belong to. Since this is the end of the serialization chain, this SaveFile is, at last, run through protobuf. The resulting byte array can be stored stored somewhere or used otherwise.

And that's really it.

Generally, you don't need to worry about these details if you're happy with the system like it is. Simply raising the right save-game events somewhere in your code will suffice and all the plumbing work is done behind the scenes.

Clone this wiki locally