Skip to main content

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.

Save Game Blueprint function

Save Game Blueprint function

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 its Context ID.
  • Get File Path: We use the Get Project Saved Directory node to find the game's Saved folder and append our desired filename.
  • Call Save Context to Json File: This is the main function from the FactsDBSerializationSubsystem. 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 check bSuccess 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 target Context 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 between JSON and Binary.
  • 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