Adding a subsystem¶
Recipe for declaring a new Game Instance or World subsystem in Rephrased. Subsystems are singletons the engine creates automatically — you do not spawn them.
Prerequisites: Actors, components, subsystems, C++ extensions, Coding conventions.
Choose a scope¶
| Base class | Lifetime | Use when |
|---|---|---|
UGameInstanceSubsystem |
Survives level loads | Cross-level managers and session state |
UWorldSubsystem |
One instance per loaded world | Per-level services and caches (UGameplayRecorderSubsystem, URuneCameraSubsystem) |
If the data should reset when the level changes, pick World. If it should persist across level transitions within one play session, pick Game Instance.
1. Add the header¶
Place new subsystem headers under Source/Rephrased/ (or the matching Source/Rephrased/RuneSystem/<Area>/ folder if it belongs to the rune stack).
Game Instance example:
#pragma once
#include "CoreMinimal.h"
#include "Subsystems/GameInstanceSubsystem.h"
#include "MyFeatureSubsystem.generated.h"
UCLASS()
class REPHRASED_API UMyFeatureSubsystem : public UGameInstanceSubsystem
{
GENERATED_BODY()
public:
virtual void Initialize(FSubsystemCollectionBase& Collection) override;
virtual void Deinitialize() override;
UFUNCTION(BlueprintCallable, Category = "My Feature")
void DoWork();
};
World example: inherit UWorldSubsystem instead and include Subsystems/WorldSubsystem.h. See UGameplayRecorderSubsystem in Source/Rephrased/GameplayRecorderSubsystem.h.
2. Implement Initialize / Deinitialize¶
#include "MyFeatureSubsystem.h"
void UMyFeatureSubsystem::Initialize(FSubsystemCollectionBase& Collection)
{
Super::Initialize(Collection);
// Bind delegates, cache subsystems — world and game instance exist here.
}
void UMyFeatureSubsystem::Deinitialize()
{
// Unbind, clear caches.
Super::Deinitialize();
}
If your subsystem must run after another, declare the dependency in Initialize:
See existing subsystems in Source/Rephrased/ for patterns.
3. Access from gameplay code¶
Game Instance:
if (UGameInstance* GI = GetWorld()->GetGameInstance())
{
if (UMyFeatureSubsystem* Sub = GI->GetSubsystem<UMyFeatureSubsystem>())
{
Sub->DoWork();
}
}
World:
4. Build rules¶
- New
.h/.cppfiles underSource/Rephrased/are picked up automatically — no module list edit for files in the game module. - After adding
UCLASS,UPROPERTY, orUFUNCTION, close the editor and rebuild from Visual Studio. Live Coding cannot add new reflected members. - First compile after a new class often takes a few minutes; incremental builds afterward are faster.
5. Verify¶
- Build Development Editor | Win64 succeeds.
- Launch editor, open LV_2ndPlayable or your personal playground, press Play.
- Confirm your subsystem logs or behavior in Output Log / gameplay as expected.
Related pages¶
- Rune system core — existing subsystem map
- Adding a verb — when the work is a verb's rules or a puzzle behavior instead of global infrastructure
- Glossary —
UPROPERTY, GC, CDO
Change history¶
- 2026-10-02 — Gabriel Li — The Adding a verb link describes verb rules and puzzle behaviors (CORE-011).
- 2026-09-17 — Gabriel Li — Scope examples and verification map use the current world subsystems and default playable map.
-
2026-09-05 — Gabriel Li — Updated sandbox references to PreProShowcase (
Content/Rephrased/Levels/Prepro/) after the content reorganization (PR #19). -
2026-05-23 — Gabriel Li — Subsystem recipe from onboarding audit follow-up.