This is the multi-page printable view of this section. Click here to print.

Return to the regular view of this page.

GS_Managers

The game lifecycle management system — startup sequencing, systemic navigation, and the extensible manager pattern.

Overview

The Managers system is the backbone of every GS_Play project. It provides a controlled startup sequence that initializes game systems in the right order, global access to those systems via EBus, and systemic navigation (New Game, Load Game, Quit) from a single point of control.

Every GS_Play gem that has a manager component (Save, Stage, UI, Unit, Camera, Audio, etc.) plugs into this system automatically.


Architecture

GameManager Entity Hierarchy

GS_GameManager                   Top-level lifecycle controller
  ├── GS_SaveManager             Persistence (save/load game data)
       ├── GS_Saver             Per-entity save components
       └── RecordKeeper         Simple key-value progression records
  ├── GS_StageManager            Level loading and navigation
       ├── GS_StageData         Per-level anchor and spin-up controller
       └── StageExitPoint       Spawn/exit position markers
  ├── GS_OptionsManager          Options and input profile management
       └── GS_InputProfile      Data asset for input bindings
  └── (Your Custom Managers)     Extend GS_Manager for your own systems

All managers follow the same pattern: they are spawned by the Game Manager, go through a two-stage initialization, and are globally accessible via their EBus interfaces.

Staged Initialization

GS_GameManager (singleton, placed in every level as a prefab)
  ├── Spawns manager prefabs from its "Startup Managers" list
  ├── Stage 1: Initialize
  │     Each manager runs Activate(), then reports OnRegisterManagerInit()
  │     GM waits for ALL managers to report before proceeding
  ├── Stage 2: Startup
  │     GM broadcasts OnStartupManagers()
  │     Each manager connects to other managers, then reports OnRegisterManagerStartup()
  │     GM waits for ALL managers to report before proceeding
  └── Stage 3: Complete
        GM broadcasts OnStartupComplete()
        Game systems are fully ready — UI can spawn, gameplay can begin

This two-stage initialization guarantees that during Stage 2, every manager is already initialized and safe to reference. This eliminates race conditions between interdependent systems.


Components

ComponentPurposeDocumentation
GS_GameManagerComponentTop-level lifecycle controller. Spawns managers, handles New Game / Load / Quit / Standby.Game Manager
GS_ManagerComponentBase class for all game system managers. Handles the two-stage init pattern automatically.Manager

Quick Start

In-level Assembly

  1. Create a Game Manager prefab with the GS_GameManagerComponent.
  2. Create Manager prefabs for each system you need.
  3. Add the manager prefab spawnables to the Game Manager’s Startup Managers list.
  4. Place the Game Manager prefab at the top of every level.
  5. The system handles initialization ordering automatically.

Creating Unique Managers

  1. Use the Manager ClassWizard template, or extend the GS_Manager class manually.
  2. Override any initialization stage methods, or utility methods.
  3. Be sure to call parent methods in any override, otherwise initialization will be missed.
  4. Create a new Prefab with your new Manager, add to the GameManager Prefab Managers list.

See Also

1 - Game Manager

The top-level game lifecycle controller — startup sequencing, systemic navigation, standby mode, and debug support.

Image showing the Game Manager component, with added manager prefabs, as seen in the Entity Inspector.

Overview

The Game Manager is the root component of every GS_Play project. It controls the game lifecycle from startup through shutdown: spawning and initializing all Manager components in the correct order, providing systemic navigation (New Game, Load Game, Return to Title, Quit), and coordinating standby mode for pausing gameplay during level transitions or other blocking operations.

Every level in your project should contain the same Game Manager prefab. This allows you to start the game from any level — in debug mode it stays in the current level, in release mode it navigates to your title stage.

How It Works

Startup Sequence

When the project starts, the Game Manager executes a three-stage startup:

  1. Spawn Managers — The Game Manager instantiates every prefab in its Startup Managers list. Each manager component runs its Activate() and reports back via OnRegisterManagerInit().
  2. Startup Managers — Once all managers report initialized, the Game Manager broadcasts OnStartupManagers(). Managers now connect to each other and report back via OnRegisterManagerStartup().
  3. Startup Complete — Once all managers report started up, the Game Manager broadcasts OnStartupComplete(). The game is fully initialized and ready to run.

At each stage, the Game Manager counts reports and only proceeds when every spawned manager has reported. This guarantees safe cross-referencing between managers in Stage 2.

Systemic Navigation

The Game Manager provides the high-level game flow methods that drive your project:

  • NewGame / NewGame(saveName) — Starts a new game, optionally with a named save file.
  • ContinueGame — Loads the most recent save and continues.
  • LoadGame(saveName) — Loads a specific save file.
  • ReturnToTitle — Returns to the title stage, tearing down the current game session.
  • SaveAndExitGame / ExitGame — Saves and/or exits the application.

These methods coordinate with the Save Manager and Stage Manager automatically.

Standby Mode

Standby is a global pause mechanism. When the Game Manager enters standby, it broadcasts OnEnterStandby() to all managers, which propagate the signal to their subsystems. This halts timers, physics, gameplay ticks, and other simulation while a blocking operation (like a stage change) completes. Calling ExitStandby reverses the process.

Debug Mode

When Debug Mode is enabled in the Inspector, the Game Manager skips navigating to the title stage and remains in the current level. This allows rapid iteration — you can start the game from any level without going through the full title-to-gameplay flow. If save data and unit management are enabled, it loads default save data but overrides position data with the current level’s default spawn point.


Setup

Image showing the Game Manager wrapper entity set as Editor-Only inside Prefab Edit Mode.

  1. Create an entity and attach the GS_GameManagerComponent (or your extended version).
  2. Turn the entity into a prefab.
  3. Enter prefab edit mode. Set the wrapper entity (the parent of your Game Manager entity) to Editor Only. Save the prefab.
  4. Create Manager prefabs for the systems you need (Save, Stage, Options, or custom managers).
  5. Add each Manager .spawnable to the Game Manager’s Startup Managers list in the Entity Inspector.
  6. Push your overrides into the prefab to propagate across all levels.

Place your Game Manager prefab at the top of every level in the Entity Outliner.

The premade manager prefabs for each GS_Play gem are located in that gem’s Assets/Prefabs directory.


Inspector Properties

PropertyTypeDescription
Project PrefixAZStd::stringSets the project prefix for generated files (e.g. save files). Example: "GS" produces GS_SaveGame.json.
Startup ManagersAZStd::vector<SpawnableAssetRef>The list of Manager prefab spawnables to instantiate on game start. Order does not matter — the two-stage init handles dependencies.
Debug ModeboolWhen enabled, the Game Manager stays in the current level instead of navigating to the title stage. Useful for rapid iteration.

API Reference

Request Bus: GameManagerIncomingEventBus

Commands you send to the Game Manager. This is a singleton bus (Single address, Single handler).

MethodParametersReturnsDescription
IsInDebugboolReturns whether debug mode is active.
IsStartedboolReturns whether the startup sequence has completed.
GetProjectPrefixAZStd::stringReturns the configured project prefix string.
EnterStandbyvoidBroadcasts standby to all managers, pausing gameplay.
ExitStandbyvoidBroadcasts standby exit, resuming gameplay.
NewGamevoidStarts a new game with default save name.
NewGameconst AZStd::string& saveNamevoidStarts a new game with a specified save file name.
ContinueGamevoidLoads the most recent save file and continues.
LoadGameconst AZStd::string& saveNamevoidLoads a specific save file by name.
ReturnToTitlevoidReturns to the title stage, tearing down the current session.
SaveAndExitGamevoidSaves the current game state and exits the application.
ExitGamevoidExits the application without saving.

Notification Bus: GameManagerOutgoingEventBus

Events broadcast by the Game Manager that other systems listen to. This is a multiple handler bus — any number of components can subscribe.

EventDescription
OnSetupManagersFired when all managers have reported initialized. Managers should now connect to each other.
OnStartupCompleteFired when the full startup sequence is complete. Safe to begin gameplay.
OnShutdownManagersFired when the game is shutting down. Managers should clean up.
OnBeginGameFired when a new game or loaded game begins.
OnEnterStandbyFired when entering standby mode. Pause your systems.
OnExitStandbyFired when exiting standby mode. Resume your systems.

ScriptCanvas Reflection

These methods are available as ScriptCanvas nodes for visual scripting:

NodeDescription
TriggerNewGameStarts a new game with default save.
TriggerNewGameWithName(saveName)Starts a new game with a named save.
TriggerContinueGameContinues from the most recent save.
TriggerLoadGame(saveName)Loads a specific save file.
TriggerReturnToTitleReturns to the title stage.
TriggerSaveAndExitGameSaves and exits.
TriggerExitGameExits without saving.

Local / Virtual Methods

Methods available when extending the Game Manager. Override these to customize behavior.

MethodDescription
InitializeManagers()Spawns the Startup Managers list. Override to add custom spawn logic.
ProcessFallbackSpawn()Handles fallback when a manager fails to spawn.
StartupManagers()Broadcasts OnStartupManagers. Override to inject logic between init and startup.
CompleteStartup()Final processing after startup. Broadcasts OnStartupComplete.
BeginGame()Called when transitioning into active gameplay.

Usage Examples

Starting a New Game from C++

#include <GS_Core/GS_CoreBus.h>

// Start a new game with a named save file
GS_Core::GameManagerIncomingEventBus::Broadcast(
    &GS_Core::GameManagerIncomingEventBus::Events::NewGame,
    AZStd::string("MySaveFile")
);

Listening for Startup Complete

#include <GS_Core/GS_CoreBus.h>

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

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

    // Called once the game is fully initialized
    void OnStartupComplete() override
    {
        // Safe to access all managers and begin gameplay logic
    }

    // Called when entering standby (e.g. during level transitions)
    void OnEnterStandby() override
    {
        // Pause your gameplay systems
    }

    void OnExitStandby() override
    {
        // Resume your gameplay systems
    }
};

Extending the Game Manager

You can extend the Game Manager to add custom startup logic, additional lifecycle events, or project-specific behavior.

Header (.h)

#pragma once
#include <GS_Core/GS_CoreBus.h>
#include <Source/Managers/GS_GameManagerComponent.h>

namespace MyProject
{
    class MyGameManager : public GS_Core::GS_GameManagerComponent
    {
    public:
        AZ_COMPONENT_DECL(MyGameManager);

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

    protected:
        void InitializeManagers() override;
        void StartupManagers() override;
        void CompleteStartup() override;
        void BeginGame() override;
    };
}

Implementation (.cpp)

#include "MyGameManager.h"
#include <AzCore/Serialization/SerializeContext.h>

namespace MyProject
{
    AZ_COMPONENT_IMPL(MyGameManager, "MyGameManager", "{YOUR-UUID-HERE}");

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

            if (AZ::EditContext* editContext = serializeContext->GetEditContext())
            {
                editContext->Class<MyGameManager>("My Game Manager", "Custom game manager for MyProject")
                    ->ClassElement(AZ::Edit::ClassElements::EditorData, "")
                        ->Attribute(AZ::Edit::Attributes::Category, "MyProject")
                        ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC_CE("Game"));
            }
        }
    }

    void MyGameManager::InitializeManagers()
    {
        // Call base to spawn the standard manager list
        GS_GameManagerComponent::InitializeManagers();

        // Add custom initialization logic here
    }

    void MyGameManager::StartupManagers()
    {
        // Call base to handle standard startup
        GS_GameManagerComponent::StartupManagers();
    }

    void MyGameManager::CompleteStartup()
    {
        // Call base to broadcast OnStartupComplete
        GS_GameManagerComponent::CompleteStartup();

        // Your post-startup logic here (e.g. connect to analytics, initialize online services)
    }

    void MyGameManager::BeginGame()
    {
        GS_GameManagerComponent::BeginGame();

        // Custom game start logic
    }
}

Module Registration

Register your custom Game Manager in your project’s module:

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

See Also

2 - Manager

The base class for all game system managers — automatic two-stage initialization and lifecycle integration with the Game Manager.

Image showing a Manager prefab with the wrapper entity set as Editor-Only inside Prefab Edit Mode.

Overview

The GS_ManagerComponent is the base class that all game system managers inherit from. It handles the two-stage initialization pattern with the Game Manager automatically, so you can focus on your system’s logic without worrying about startup ordering.

Every built-in GS_Play manager (Save, Stage, Options, UI, Unit, Camera, Audio, Performer) extends this class. When you need a custom game system manager, you extend it too.

How It Works

When the Game Manager spawns its list of manager prefabs, each Manager component goes through this lifecycle:

  1. Activate — The component initializes itself (connects to buses, sets up internal state). When done, it broadcasts OnRegisterManagerInit() to tell the Game Manager it is ready.

  2. OnStartupManagers — Called by the Game Manager after all managers have reported initialized. This is where you connect to other managers and set up cross-references. When done, broadcasts OnRegisterManagerStartup().

  3. OnStartupComplete — The Game Manager broadcasts this after all managers report started up. The game is fully ready.

  4. OnEnterStandby / OnExitStandby — Called when the Game Manager enters or exits standby mode. Pause and resume your subsystem here.

  5. OnShutdownManagers — Called when the game is shutting down. Clean up your subsystem.

The base class handles steps 1-2 automatically — you override them to add your own logic, then call the base implementation to complete the handshake.


Setup

Image showing the Manager wrapper entity set as Editor-Only inside Prefab Edit Mode.

  1. Create an entity. Attach your Manager component (built-in or custom) to it.
  2. Configure any properties needed in the Entity Inspector.
  3. Turn the entity into a prefab.
  4. Enter prefab edit mode. Set the wrapper entity (parent of your Manager entity) to Editor Only. Save.
  5. Delete the Manager entity from the level (it will be spawned by the Game Manager at runtime).
  6. In the Game Manager prefab, add your Manager .spawnable to the Startup Managers list.

The premade manager prefabs for each GS_Play gem are located in that gem’s Assets/Prefabs directory.


Inspector Properties

The base GS_ManagerComponent exposes no inspector properties of its own. Properties are defined by each inheriting manager component (e.g., the Save Manager exposes a Save System Version Number, the Stage Manager exposes a Stages list).


API Reference

Lifecycle Bus: GameManagerOutgoingEventBus

The Manager base class automatically subscribes to these events from the Game Manager:

EventWhen It FiresWhat You Do
OnStartupManagersAll managers are initializedConnect to other managers, set up cross-references, then call base to report.
OnStartupCompleteAll managers are started upBegin runtime operation.
OnEnterStandbyGame is entering standbyPause your subsystem (stop ticks, halt processing).
OnExitStandbyGame is exiting standbyResume your subsystem.
OnShutdownManagersGame is shutting downClean up resources, disconnect buses.

Registration Methods

These are called internally by the Manager base class to report back to the Game Manager:

MethodDescription
OnRegisterManagerInit()Called at the end of Activate(). Reports to the Game Manager that this manager has initialized.
OnRegisterManagerStartup()Called at the end of OnStartupManagers(). Reports to the Game Manager that this manager has started up.

Usage Examples

Checking if the Game Manager is Ready

#include <GS_Core/GS_CoreBus.h>

bool isStarted = false;
GS_Core::GameManagerIncomingEventBus::BroadcastResult(
    isStarted,
    &GS_Core::GameManagerIncomingEventBus::Events::IsStarted
);

if (isStarted)
{
    // Safe to access all managers
}

Extending the Manager Class

Create a custom manager whenever you need a singleton game system that initializes with the rest of the framework.

Header (.h)

#pragma once
#include <Source/Managers/GS_ManagerComponent.h>

// Define your EBus interface for other systems to call your manager
class MyManagerRequests
{
public:
    AZ_RTTI(MyManagerRequests, "{YOUR-UUID-HERE}");
    virtual ~MyManagerRequests() = default;

    virtual int GetSomeValue() = 0;
    virtual void DoSomething() = 0;
};

class MyManagerBusTraits : public AZ::EBusTraits
{
public:
    static constexpr AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
    static constexpr AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
};

using MyManagerRequestBus = AZ::EBus<MyManagerRequests, MyManagerBusTraits>;

namespace MyProject
{
    class MyManagerComponent
        : public GS_Core::GS_ManagerComponent
        , protected MyManagerRequestBus::Handler
    {
    public:
        AZ_COMPONENT_DECL(MyManagerComponent);

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

    protected:
        // Manager lifecycle
        void Activate() override;
        void Deactivate() override;
        void OnStartupManagers() override;
        void OnEnterStandby() override;
        void OnExitStandby() override;

        // Your bus implementation
        int GetSomeValue() override;
        void DoSomething() override;

    private:
        int m_someValue = 0;
    };
}

Implementation (.cpp)

#include "MyManagerComponent.h"
#include <AzCore/Serialization/SerializeContext.h>

namespace MyProject
{
    AZ_COMPONENT_IMPL(MyManagerComponent, "MyManagerComponent", "{YOUR-UUID-HERE}");

    void MyManagerComponent::Reflect(AZ::ReflectContext* context)
    {
        if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
        {
            serializeContext->Class<MyManagerComponent, GS_Core::GS_ManagerComponent>()
                ->Version(0)
                ->Field("SomeValue", &MyManagerComponent::m_someValue);

            if (AZ::EditContext* editContext = serializeContext->GetEditContext())
            {
                editContext->Class<MyManagerComponent>("My Manager", "A custom game system manager")
                    ->ClassElement(AZ::Edit::ClassElements::EditorData, "")
                        ->Attribute(AZ::Edit::Attributes::Category, "MyProject")
                        ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC_CE("Game"))
                    ->DataElement(AZ::Edit::UIHandlers::Default,
                        &MyManagerComponent::m_someValue, "Some Value", "Description of this property");
            }
        }
    }

    void MyManagerComponent::Activate()
    {
        // Connect your bus
        MyManagerRequestBus::Handler::BusConnect();

        // IMPORTANT: Call base Activate last — it reports OnRegisterManagerInit()
        GS_ManagerComponent::Activate();
    }

    void MyManagerComponent::Deactivate()
    {
        MyManagerRequestBus::Handler::BusDisconnect();
        GS_ManagerComponent::Deactivate();
    }

    void MyManagerComponent::OnStartupManagers()
    {
        // Access other managers here — they are all initialized by now
        // Example: query the Save Manager, connect to the Stage Manager, etc.

        // IMPORTANT: Call base last — it reports OnRegisterManagerStartup()
        GS_ManagerComponent::OnStartupManagers();
    }

    void MyManagerComponent::OnEnterStandby()
    {
        // Pause your subsystem
    }

    void MyManagerComponent::OnExitStandby()
    {
        // Resume your subsystem
    }

    int MyManagerComponent::GetSomeValue()
    {
        return m_someValue;
    }

    void MyManagerComponent::DoSomething()
    {
        // Your game system logic
    }
}

Module Registration

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

Then create a prefab for your manager and add it to the Game Manager’s Startup Managers list.


See Also