
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):
- BeginSave() — Primes the save data container.
- BuildSaveData() — Your override. Gather your component’s data and write it into
localDatausing the Save Manager’s JSON allocator. - CompleteSave() — Submits the data to the Save Manager via
SaveData(uniqueName, localData).
Load Cycle
When a load event fires (global OnLoadAll or loadOnActivate):
- LoadLocalData() — Retrieves this Saver’s data block from the Save Manager via
LoadData(uniqueName, outData). - 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
- Attach a Saver component (built-in or custom) to any entity that needs to persist data.
- 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.
- Ensure the Save Manager is set up and running (it handles the file I/O).
Inspector Properties
| Property | Type | Default | Description |
|---|---|---|---|
| Load On Activate | bool | true | Automatically 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 Destroy | bool | true | Automatically 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.
| Method | Description |
|---|---|
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.
| Method | Description |
|---|---|
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.
| Method | Description |
|---|---|
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
| Method | Returns | Description |
|---|---|---|
SetUniqueName() | void | Generates the unique save key from the entity name and sub-component name. Override for custom key generation. |
GetSubComponentName() | AZStd::string | Returns "Saver" by default. Override to distinguish multiple Saver types on the same entity. |
Components
Pre-built Saver components included in GS_Core:
| Component | Saves | Documentation |
|---|---|---|
| BasicEntitySaverComponent | Entity Transform (position, rotation) | List of Savers |
| BasicPhysicsEntitySaverComponent | Entity Transform + Rigidbody (position, rotation, linear velocity, angular velocity) | List of Savers |
| RecordKeeperComponent | Key-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
- Save Manager — Central save/load controller
- Record Keeper — Lightweight key-value records (no custom class needed)
- List of Savers — Pre-built saver components
- Templates — Starter files for custom savers