Saving and Loading
Table of Contents
The state of state charts can be saved and loaded with the built-in StateChartSerializer
class. When saving, this will produce a SerializedStateChart
resource, which can be added to your own saved game resource or be converted into a savefile format of your choice (e.g. JSON). The serializer can also be used to load the state chart back into your game, restoring the state of the chart and its states.
⚠️ Note: saving and loading of
AnimationPlayer
andAnimationStateTree
states is not supported, as both of these states are deprecated.
Saving
To get a saved resource file representing the current state of your state tree, call StateChartSerializer.serialize(my_state_chart)
in your save game method. This will return a SerializedStateChart
object. From here, you can either save it to storage with the built-in ResourceSaver
or convert it into other formats as needed.
See the demo games folder for an example of saving game objects and state chart state together (inside the save_and_load
directory).
Here’s an annotated example from save_and_load
:
func save_state() -> void:
# set the save file path
var path = "user://save_resource.tres"
# instantiate a global save resource (with a reference to SerializedStateChart)
var save_resource: SaveResource = SaveResource.new()
# create the populated SerializedStateChart with the current state
# SaveResource contains @export var state_chart: SerializedStateChart
save_resource.state_chart = StateChartSerializer.serialize(chart)
# save my non-state-chart game data:
...
# save to the path from above
ResourceSaver.save(save_resource, path)
This will save the active status of all states of the state chart as well as any pending transitions and their timings.
C# Example
Here’s how you can save the state chart in C#:
public void SaveState()
{
// Set the save file path
var path = "user://save_resource.tres";
// Instantiate a global save resource (with a reference to SerializedStateChart)
var saveResource = new SaveResource();
// Create the populated SerializedStateChart with the current state
var serializedStateChart = StateChartSerializer.Serialize(chart);
// Because SerializedStateChart is a wrapper around Resource,
// SaveResource contains: [Export] public Resource StateChart;
saveResource.StateChart = serializedStateChart.Wrapped;
// Save other non-state-chart game data
...
// Save to the path from above
ResourceSaver.Save(path, saveResource);
}
Loading
Loading requires reversing the process to populate a SerializedStateChart
and it’s children, then passing that into the StateChartSerializer.deserialize(...)
method. How you do this, depends on your game’s needs, but a simple way would be to load a SerializedStateChart
back from a file with Godot’s build-in ResourceLoader
class.
It’s important to note that the StateChartSerializer
updates an existing state chart in your tree on which the state that was previously saved in SerializedStateChart
is applied. It does not recreate StateChart
or StateChartState
nodes from scratch. This is because your scenes already contain state charts which have signals connected to your code and recreating this structure would be very error prone, or downright impossible in some cases.
Here’s an annotated example of loading from save_and_load
demo game:
# This is the state chart that is currently in the tree and
# onto which we want to apply the state that we previously
# have saved.
var chart:StateChart
func load_state() -> void:
# set the file path to your saved game
var path = "user://save_resource.tres"
# load the global save resource from the file
var save_resource: SaveResource = ResourceLoader.load(path, "SaveResource")
# restore state chart internal state
StateChartSerializer.deserialize(save_resource.state_chart, chart)
# load other non-state-chart data
...
C# Example
Here’s how you can load the state chart in C#:
// This is the state chart that is currently in the tree and
// onto which we want to apply the state that we previously saved.
private StateChart chart;
public void LoadState()
{
// Set the file path to your saved game
var path = "user://save_resource.tres";
// Load the global save resource from the file
var saveResource = ResourceLoader.Load<SaveResource>(path);
// Create a wrapper object around the loaded SerializedStateChart
var serializedStateChart = SerializedStateChart.Of(saveResource.StateChart);
// Restore state chart internal state
StateChartSerializer.Deserialize(serializedStateChart, chart);
// Load other non-state-chart data
...
}
Save game evolution
When you change the state chart definition in your game (e.g. add states, remove states, rename states, change state types, add/remove transitions) then previously saved instances of SerializedStateChart
will become incompatible with your current state chart definition. StateChartSerializer
will ensure that the StateChart
in the tree exactly matches the structure of the SerializedStateChart
before trying to restore the internal state. If the both do not exactly match, then the StateChartSerializer
will refuse to restore the state and return a list of error messages detailing the problems. The running state chart will not be modified if SerializedStateChart
is not compatible. This is to ensure consistent, predictable behaviour.
If your state charts have evolved, you will need to write additional code that patches SerializedStateChart
resources to match the new structure of your state chart. It might also be necessary to change some internals (e.g. which state is currently active) to ensure predictable behaviour for your game. It is recommended that you wrap SerializedStateChart
into your own saved game resource (like we did in the examples) and add a game_version
property to this resource, so you can keep track of which version of your game saved the state chart. This way you can run migration logic when loading your game.
Note that SerializedStateChart
also has a version
property, which the StateChartSerializer
uses to do the same thing, in case this library changes how it serializes state charts. This field is reserved for the StateChartSerializer
so do not use it to track your game version.