Savers

The base class for entity-level save handlers — override BuildSaveData() and ProcessLoad() to persist any component data automatically.

Image showing the Basic Physics Saver component, an example of a Saver-inherited class, as seen in the Entity Inspector.

Overview

The GS_SaverComponent is the base class for all entity-level save handlers. By extending it, you can create companion components that save and load data alongside your entities, or inherit directly into gameplay components for built-in persistence (as done by GS_Inventory).

Savers automatically participate in the global save/load cycle — when the Save Manager broadcasts OnSaveAll or OnLoadAll, every active Saver component responds by gathering or restoring its data.

How It Works

Save Cycle

When a save event fires (global OnSaveAll, local trigger, or saveOnDestroy):

  1. BeginSave() — Primes the save data container.
  2. BuildSaveData() — Your override. Gather your component’s data and write it into localData using the Save Manager’s JSON allocator.
  3. CompleteSave() — Submits the data to the Save Manager via SaveData(uniqueName, localData).

Load Cycle

When a load event fires (global OnLoadAll or loadOnActivate):

  1. LoadLocalData() — Retrieves this Saver’s data block from the Save Manager via LoadData(uniqueName, outData).
  2. ProcessLoad() — Your override. Read the retrieved data and restore your component’s state.

Automatic Identity

Each Saver generates a unique save key from the entity name and GetSubComponentName(). This ensures multiple Savers on different entities (or multiple Saver types on the same entity) don’t collide.


Setup

  1. Attach a Saver component (built-in or custom) to any entity that needs to persist data.
  2. Configure the Saver properties:
    • Load On Activate — restore data automatically when the entity spawns.
    • Save On Destroy — save data automatically when the entity is destroyed.
  3. Ensure the Save Manager is set up and running (it handles the file I/O).

Inspector Properties

PropertyTypeDefaultDescription
Load On ActivatebooltrueAutomatically loads and restores this Saver’s data when the component activates. Useful for entities that spawn mid-game and need to resume their saved state.
Save On DestroybooltrueAutomatically saves this Saver’s data when the component is destroyed. Ensures data is captured even if a global save hasn’t been triggered.

API Reference

Global Event Handlers

These are called automatically when the Save Manager broadcasts global save/load events. Override to customize behavior.

MethodDescription
OnSaveAll()Called when the Save Manager broadcasts a global save. Default implementation calls the full save cycle (BeginSave → BuildSaveData → CompleteSave).
OnLoadAll()Called when the Save Manager broadcasts a global load. Default implementation calls the full load cycle (LoadLocalData → ProcessLoad).

Save Methods

Override these to control how your component’s data is saved.

MethodDescription
BeginSave()Prepares the save data container. Called before BuildSaveData().
BuildSaveData()Your primary override. Write your component’s data into localData using the JSON allocator.
CompleteSave()Submits localData to the Save Manager. Called after BuildSaveData().

Load Methods

Override these to control how your component’s data is restored.

MethodDescription
LoadLocalData()Retrieves this Saver’s data block from the Save Manager into localData.
ProcessLoad()Your primary override. Read localData and restore your component’s state.

Utility Methods

MethodReturnsDescription
SetUniqueName()voidGenerates the unique save key from the entity name and sub-component name. Override for custom key generation.
GetSubComponentName()AZStd::stringReturns "Saver" by default. Override to distinguish multiple Saver types on the same entity.

Components

Pre-built Saver components included in GS_Core:

ComponentSavesDocumentation
BasicEntitySaverComponentEntity Transform (position, rotation)List of Savers
BasicPhysicsEntitySaverComponentEntity Transform + Rigidbody (position, rotation, linear velocity, angular velocity)List of Savers
RecordKeeperComponentKey-value records (string → integer)Record Keeper

Usage Examples

Responding to Global Save/Load Events

If your component doesn’t extend GS_SaverComponent but still needs to react to save/load events, connect to the SaveManagerOutgoingEventBus:

#include <GS_Core/GS_CoreBus.h>

class MyComponent
    : public AZ::Component
    , protected GS_Core::SaveManagerOutgoingEventBus::Handler
{
protected:
    void Activate() override
    {
        GS_Core::SaveManagerOutgoingEventBus::Handler::BusConnect();
    }

    void Deactivate() override
    {
        GS_Core::SaveManagerOutgoingEventBus::Handler::BusDisconnect();
    }

    void OnSaveAll() override
    {
        // Gather and submit data to the Save Manager
    }

    void OnLoadAll() override
    {
        // Retrieve and restore data from the Save Manager
    }
};

Extending the Saver Class

Create a custom Saver whenever you need to persist component-specific data that the built-in savers don’t cover.

Header (.h)

#pragma once
#include <Source/SaveSystem/GS_SaverComponent.h>

namespace MyProject
{
    class MyEntitySaverComponent
        : public GS_Core::GS_SaverComponent
    {
    public:
        AZ_COMPONENT_DECL(MyEntitySaverComponent);

        static void Reflect(AZ::ReflectContext* context);

    protected:
        // Saver overrides
        void BuildSaveData() override;
        void ProcessLoad() override;
        AZStd::string GetSubComponentName() const override { return "MyEntitySaver"; }
    };
}

Implementation (.cpp)

#include "MyEntitySaverComponent.h"
#include <AzCore/Serialization/SerializeContext.h>
#include <GS_Core/GS_CoreBus.h>

namespace MyProject
{
    AZ_COMPONENT_IMPL(MyEntitySaverComponent, "MyEntitySaverComponent", "{YOUR-UUID-HERE}",
        GS_Core::GS_SaverComponent);

    void MyEntitySaverComponent::Reflect(AZ::ReflectContext* context)
    {
        if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
        {
            serializeContext->Class<MyEntitySaverComponent, GS_Core::GS_SaverComponent>()
                ->Version(0);

            if (AZ::EditContext* editContext = serializeContext->GetEditContext())
            {
                editContext->Class<MyEntitySaverComponent>(
                    "My Entity Saver", "Saves custom entity data")
                    ->ClassElement(AZ::Edit::ClassElements::EditorData, "")
                        ->Attribute(AZ::Edit::Attributes::Category, "MyProject")
                        ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC_CE("Game"));
            }
        }
    }

    void MyEntitySaverComponent::BuildSaveData()
    {
        // Get the JSON allocator from the Save Manager
        rapidjson::Document::AllocatorType* allocator = nullptr;
        GS_Core::SaveManagerIncomingEventBus::BroadcastResult(
            allocator,
            &GS_Core::SaveManagerIncomingEventBus::Events::GetAllocator
        );

        if (!allocator) return;

        // Write your data into localData (inherited member)
        localData.SetObject();
        localData.AddMember("myValue", 42, *allocator);
        localData.AddMember("myFlag", true, *allocator);

        // Example: save a string
        rapidjson::Value nameVal;
        nameVal.SetString("hello", *allocator);
        localData.AddMember("myString", nameVal, *allocator);
    }

    void MyEntitySaverComponent::ProcessLoad()
    {
        // Read your data from localData (populated by LoadLocalData)
        if (localData.HasMember("myValue"))
        {
            int myValue = localData["myValue"].GetInt();
            // ... restore state ...
        }

        if (localData.HasMember("myFlag"))
        {
            bool myFlag = localData["myFlag"].GetBool();
            // ... restore state ...
        }
    }
}

Module Registration

m_descriptors.insert(m_descriptors.end(), {
    MyProject::MyEntitySaverComponent::CreateDescriptor(),
});

Attach your custom Saver to any entity that needs persistence. The save/load cycle handles the rest automatically.


See Also


List of Savers

Pre-built saver components included in GS_Core — ready-to-use entity persistence without writing code.