Save Game

Save Games are crucial for keeping state information of machines and such between game sessions. The save games contain information about stuff like what items are in your inventory. Normally Satisfactory saves the current game state periodically every 5 minutes as an autosave. And, of course, you can save the game state yourself by pressing the Save button in game.

You can find your save files in %localappdata%/FactoryGame/Saved/SaveGames/

But what actually happens when you push this magical "Save" button?

How is the game state saved?

When a save gets loaded or saved, unreal is going to serialize the currently loaded world. This process basically allows to convert all the actors and objects in the runtime into some binary data that can later again be read to recreate the current runtime.

But we don’t save the whole runtime because this would make save files way to big, instead many things are excluded from the serialization in multiple different ways. As default, your stuff is not going to be serialized, that means we need to tell unreal that we want to get serialized.

Every AActor or UActorComponent in the world is considered to get serialized, but because this would still be to much, CSS added the IFGSaveInterface which allows for further filtering. If you have some kind of AActor and it should get serialized you need to override the ShouldSave function and return true.

When the actor gets serialized this happens in two stages.

In the first stage, a unreal serialization process is executed but only cares about possible serialized UObjects. So it basically collects in this stage a list of all UObjects that need to get serialized. Afterwards CSS sorts this list considering the results of IFGSaveInterface::GatherDependencies which allows a UObject to further define on which UObjects it depends on.

This is sometimes important for the deserialization step on save load, because you might want your dependent UObjects to get fully deserialized first.

Make sure you don’t cause circular dependencies when working with IFGSaveInterface::GatherDependencies.

In the second state, the real unreal serialization process is executed while considering the previously determined UObject order.

The "unreal serialization" can happen in two ways, either you implement your own serialization process by overriding the Serialize function or by using the unreal’s default way via UProperties (recommended). You should look up the unreal documentation for more information on how to add custom serialization to UObjects or structs if needed.

The unreal default way of serialization simply searches for UProperties that don’t have the SkipSerialization-Property-Flag and have the SaveGame-Property-Flag. If the UProperty is a UObject reference, this UObject also gets serialized.

While such a serialization is ongoing, the Satisfactory Save System also calls the PreSaveGame, PostSaveGame, PreLoadGame and PostLoadGame functions on all the AActors with the IFGSaveInterface that are getting serialized.

image

The SaveGame UProperty Flag

Not all attributes of a object get serialized, only UProperties marked with the SaveGame-Flag get actually serialized.

When working with Blueprints you can add this flag by opening the advanced property settings and checking the SaveGame box.

When working with C++ you should follow the directions below for using IFGSaveInterface.

Make sure you have not set the SkipSerialization flag on the property or the object. This would end in the save system wanting to save but the Unreal serializer just ignoring your data.

But by default, it shouldn’t be set.

Note that not all types can be directly saved. Examples include the Soft Class Reference and Soft Object Reference types. In this case you must write code to serialize the type yourself as described above. For the Soft Class Reference example, instead of having the Soft Class Reference property saved, instead have a saved String property that PreSaveGame copies out of and PostLoadGame populates the "real" field from respectively.

The IFGSaveInterface

The save system of Satisfactory uses the IFGSaveInterface to filter now between objects we need to save, and objects we don’t need to save.

On of the most important functions is the bool ShouldSave() const function, which returns true when the object should get saved. This can be dependent on the sate of the object, like the trees. The trees only return true if they are actually chopped down ingame.

This means, when you have information you want to keep between game sessions, you should implement IFGSaveInterface and return on ShouldSave true.

FGBuildable implements IFGSaveInterface already, but it doesn’t return true in ShouldSave, so please make sure you overwrite the function and return true.

All of the other functions allow you to further customize the serialization and filter process when the save state gets stored or loaded.

Saving Per-Player Data

You may encounter a situation where you want to save data per-player in a multiplayer game without it being tied to any tangible game object like a building or equipment item. The best way to implement this is with Simple Construction Script (SCS) Hooks.

Where Modded Save Content Ends Up

If you’d like, you can take a look at some of your modded saves in a save editor to how and where they save their data.

Generally, content created by mods appears under Game/<mod_reference>/ tag.

Here is a screenshot from SatisfactorySaveEditor displaying data from a mod with the reference NogsOres.

image