Advanced: Serialization and Persistence
FactsDB includes a powerful, built-in subsystem for serialization, which is the process of converting the live state of your fact contexts into a format that can be saved to a file or sent over a network. This is the foundation for creating save game systems, player profile data, or even for debugging by saving "snapshots" of your game's state.
The system is managed by the UFactsDBSerializationSubsystem
.
Core Concepts
Formats
The serialization system supports two primary formats, controlled by the EFactSerializationFormat
enum:
-
JSON (
.json
):- Pros: Human-readable, great for debugging, easy to diff in version control (like Git), and can be used by external tools.
- Cons: Larger file sizes and slower to parse than binary.
- Best For: Debug snapshots, save games during development, data that needs to be read or modified by hand.
-
Binary (
.factbin
):- Pros: Very compact file size and significantly faster to process.
- Cons: Not human-readable.
- Best For: Shipping build save games, large amounts of data where performance and file size are critical.
Operations
The subsystem provides functions to save/load either a single context or all active contexts at once. These operations can target a file on disk or an in-memory FString
.
Saving and Loading a Single Context
This is the most common use case, typically used for saving an individual object's state, like the player's data.
Example: Creating a Simple Save/Load System
Here's how you could implement Save Game
and Load Game
functions in a Game Instance or Game Mode Blueprint.
1. The Save Game Function
This function will get the player's Context ID
and save all of its facts to a file named PlayerSave.json
.
- Get Player's Context ID: First, we get a reference to the player's
UFactsComponent
and retrieve itsContext ID
. - Get File Path: We use the
Get Project Saved Directory
node to find the game'sSaved
folder and append our desired filename. - Call
Save Context to Json File
: This is the main function from theFactsDBSerializationSubsystem
. We pass it the Context ID and the file path. It handles all the work of converting the data to JSON and writing it to the disk. - Check Result: The function returns a
FFactSerializationOperationResult
. We can checkbSuccess
to see if the save was successful.
2. The Load Game Function
This function reads the data from PlayerSave.json
and imports it back into the player's live UFactsComponent
.
- Prerequisite: The
UFactsComponent
for the player must already exist in the world before you can load data into it. Loading should typically happen after the player has spawned and their component has been initialized. - Get Player's Context ID and File Path: Same as saving.
- Call
Load Context from File
: We provide the targetContext ID
and the path to the save file. The subsystem automatically detects the format (JSON or Binary) and deserializes it. - Import Logic: The subsystem then finds the component matching the
Context ID
and intelligently updates its facts with the loaded data. It will skip read-only facts and ensure data types match.
Saving/Loading All Contexts
The Save All Contexts to File
and Load All Contexts from File
functions work similarly, but they operate on every active UFactsComponent
registered with the subsystem.
- Use Case: This is perfect for creating a "snapshot" of the entire game world's state for debugging, or for a quick-save feature in a single-player game.
- Loading Behavior: When loading an "all contexts" file, the subsystem will iterate through the data. For each
Context ID
found in the file, it will try to find a matching live component in the world and import the data. If a component for a given ID doesn't exist, its data is simply skipped.
Serialization Options (FFactSerializationOptions
)
The save functions include an Options
struct that provides more control:
Format
: Explicitly choose betweenJSON
andBinary
.bCompressJsonOutput
: (JSON only) If true, the resulting JSON will be compressed with Zlib before being written. This can significantly reduce file size but makes it non-human-readable.bPrettyPrintJson
: (JSON only) If true, the JSON will be formatted with indentation. If false, it will be condensed into a single line.bCreateBackup
: If true, before overwriting an existing save file, the system will rename the old file with a timestamped.bak
extension. This is a safety feature to prevent accidental data loss.
Next Up: Best Practices