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 |
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.
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 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.
|
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.