Files
UE5-Modular-Game-Framework/docs/developer/cpp-integration-guide.md
Lefteris Notas 4a7c871f29 Update Developer Reference and add C++ Integration Guide
- Updated version in INDEX.md from 1.3 to 1.4, reflecting new files and C++ systems migrated.
- Added cpp-integration-guide.md detailing setup and usage for 12 C++ classes.
- Introduced cpp-blueprint-status.md to track the status of all 135 systems, including C++ and Blueprint specifications.
2026-05-20 15:16:32 +03:00

21 KiB

C++ Integration Guide — UE5 Modular Game Framework

Version: 1.0 | Generated: 2026-05-20 | Systems: 12 C++ classes | Pages: Full per-system setup

This guide covers every C++ class in Source/Framework/. For each system: what Blueprint child to create, what Project Settings to change, what assets to assign, and how other systems call into it.


Setup Before You Start

1. Add Framework Module to Your Project

In Source/YourProject/YourProject.Build.cs:

PublicDependencyModuleNames.Add("Framework");

In Source/YourProject.Target.cs:

ExtraModuleNames.Add("Framework");

2. Verify GameplayTags Plugin

YourProject.uproject must include:

"Plugins": [
    { "Name": "GameplayTags", "Enabled": true }
]

3. Create 11 Per-Category Data Tables

Before any C++ code compiles usefully, create 11 Data Tables in Content/Framework/Core/DataTables/ with Row Structure = GameplayTagTableRow. Register all 11 in Project Settings → GameplayTags → Gameplay Tag Table List.


System 01 — DA_GameTagRegistry

C++ Class

Header Source/Framework/Public/Core/DA_GameTagRegistry.h
Source Source/Framework/Private/Core/DA_GameTagRegistry.cpp
Parent UPrimaryDataAsset
Blueprint Child Not needed — use directly as a Data Asset instance

Data Asset Setup

  1. Right-click in Content Browser → Miscellaneous → Data Asset
  2. Class: DA_GameTagRegistry
  3. Name: DA_GameTagRegistry
  4. Save to: Content/Framework/Core/
  5. Open the asset → assign the TagDataTables array with all 11 Data Tables

Usage Pattern

// From any C++ code:
UDA_GameTagRegistry* Registry = LoadObject<UDA_GameTagRegistry>(...);

// Validate a tag:
bool bValid = Registry->ValidateTag(SomeTag);

// Get all tags:
TArray<FGameplayTag> AllTags = Registry->GetAllRegisteredTags();

// Create tag from string:
FGameplayTag Tag = Registry->RequestTag(FName("Framework.Player.State.Alive"));
// In Blueprint: Load Data Asset → cast to DA_GameTagRegistry → call functions
// All functions are BlueprintCallable/Pure — identical API to BP-only version

Key Win vs Blueprint

The BP version required nested ForEachLoop over 11 Data Tables. C++ calls UGameplayTagsManager::Get().RequestAllGameplayTags() — one line.


System 02 — FL_GameUtilities

C++ Class

Header Source/Framework/Public/Core/FL_GameUtilities.h
Source Source/Framework/Private/Core/FL_GameUtilities.cpp
Parent UBlueprintFunctionLibrary
Blueprint Child None — static function library, callable from anywhere

Usage Pattern

// Template subsystem access — single call replaces 3 BP nodes:
USS_SaveManager* SaveMgr = UFL_GameUtilities::GetSubsystemSafe<USS_SaveManager>(this);

// Math:
float Remapped = UFL_GameUtilities::RemapFloat(0.5f, 0.0f, 1.0f, 0.0f, 100.0f); // → 50.0

// Tag creation:
FGameplayTag Tag = UFL_GameUtilities::MakeTagFromString(TEXT("Framework.Player.State.Alive"));

// Debug (stripped from shipping):
UFL_GameUtilities::DebugLog(TEXT("Hello"), true, 5.0f, FColor::Green);
// All UFUNCTIONS appear in Blueprint context menu under "Framework|Utilities"
// Template function not callable from BP — use "Get Game Framework" / "Get Subsystem by Class" nodes

Key Win vs Blueprint

Replaces "Get Game Instance → Get Subsystem(Class)" chains everywhere with one template call.


System 03/04 — GI_GameFramework (I_InterfaceLibrary has no setup)

C++ Class

Header Source/Framework/Public/Core/GI_GameFramework.h
Source Source/Framework/Private/Core/GI_GameFramework.cpp
Parent UGameInstance
Blueprint Child to Create BP_GameFramework (or use GI_StarterGameInstance BP for early prototyping)

Project Settings

  1. Project Settings → Maps & Modes → Game Instance Class → Set to your BP child of GI_GameFramework
  2. Open the BP → Class Defaults → assign TagRegistry to the DA_GameTagRegistry Data Asset

Blueprint Child Setup

  1. Create Blueprint Class → Parent: GI_GameFramework
  2. Name: BP_GameFramework
  3. In Class Defaults:
    • TagRegistry → assign DA_GameTagRegistry
    • bValidateTagsOnInittrue
    • bLogTagsOnInitfalse (true for debugging)

Usage Pattern

// Get the framework from anywhere:
UGI_GameFramework* FW = Cast<UGI_GameFramework>(GetGameInstance());

// Change game phase:
FW->SetGamePhase(EGamePhase::InGame);

// Session flags:
FW->SetSessionFlag(Tag, true);
bool bFlag = FW->GetSessionFlag(Tag);

// Type-safe subsystem access:
USS_SaveManager* Save = FW->GetService<USS_SaveManager>();

// Check if framework ready:
if (FW->IsFrameworkReady()) { ... }

// Bind to dispatchers:
FW->OnFrameworkReady.AddDynamic(this, &UMyClass::OnReady);
FW->OnGamePhaseChanged.AddDynamic(this, &UMyClass::OnPhaseChange);

Replace GI_StarterGameInstance

When ready for the full GameInstance:

  1. Make BP_GameFramework your Game Instance Class in Project Settings
  2. Update any Cast to GI_StarterGameInstanceCast to GI_GameFramework
  3. Both share the OnFrameworkReady dispatcher — bindings are compatible

System 05 — GM_CoreGameMode

C++ Class

Header Source/Framework/Public/Core/GM_CoreGameMode.h
Source Source/Framework/Private/Core/GM_CoreGameMode.cpp
Parent AGameModeBase
Blueprint Child to Create BP_CoreGameMode

Blueprint Child Setup

  1. Create Blueprint Class → Parent: GM_CoreGameMode
  2. Name: BP_CoreGameMode
  3. In Class Defaults:
    • GameState Class → your BP_CoreGameState
    • PlayerController Class → your BP_CorePlayerController
    • Default Pawn Class → your player pawn
    • HUD Class → your WBP_HUDController

Project Settings

Project Settings → Maps & Modes → Default GameModeBP_CoreGameMode

Usage Pattern

AGM_CoreGameMode* GM = Cast<AGM_CoreGameMode>(GetWorld()->GetAuthGameMode());

// Chapter transition:
GM->TransitionToChapter(ChapterTag);

// Death routing:
GM->HandlePlayerDead(DeadController);

// Ending trigger:
GM->TriggerEnding(EndingTag);

// Pause check:
if (GM->bPauseAllowed) { /* show pause menu */ }

Key Win vs Blueprint

Server-authoritative HasAuthority() gates are compile-time checked. Chapter transitions are level-agnostic (tag-driven, no hardcoded map names).


System 06 — GS_CoreGameState

C++ Class

Header Source/Framework/Public/Core/GS_CoreGameState.h
Source Source/Framework/Private/Core/GS_CoreGameState.cpp
Parent AGameStateBase
Blueprint Child to Create BP_CoreGameState

Usage Pattern

AGS_CoreGameState* GS = GetGameState<AGS_CoreGameState>();

// Set chapter (server only — auto-replicates):
GS->SetChapter(ChapterTag);

// Add objective:
GS->AddObjective(ObjectiveTag);

// Bind to dispatchers:
GS->OnChapterChanged.AddDynamic(this, &UMyHUD::OnChapterChanged);
GS->OnObjectiveTagsChanged.AddDynamic(this, &UMyHUD::RefreshObjectives);
GS->OnEncounterActiveStateChanged.AddDynamic(this, &UMyHUD::OnEncounterToggle);

Multiplayer

All 5 variables are fully replicated with OnRep_ handlers. UI widgets bind to dispatchers — they fire for both local (server/listen-host) and remote (OnRep) clients with zero code changes.


System 07 — DA_ItemData

C++ Class

Header Source/Framework/Public/Inventory/DA_ItemData.h
Source Source/Framework/Private/Inventory/DA_ItemData.cpp
Parent UPrimaryDataAsset
Blueprint Child Not needed — create Data Asset instances per item

Data Asset Instance Setup

  1. Right-click → Miscellaneous → Data Asset
  2. Class: DA_ItemData
  3. Name: DA_Item_[Name] (e.g. DA_Item_MedKit)
  4. Fill in properties — the editor hides irrelevant fields based on ItemType

Editor UX Win

The C++ EditCondition metadata means:

  • When ItemType = Weapon, EquipmentData shows (Damage, FireRate, MagazineSize...)
  • When ItemType = Consumable, ConsumableData shows (HealthRestore, StressReduce...)
  • When bHasInspectMode = false, InspectData is hidden entirely

Usage Pattern

UDA_ItemData* Item = LoadObject<UDA_ItemData>(...);

// Validate:
FString Errors;
if (!Item->ValidateItemData(Errors))
{
    UE_LOG(..., Warning, TEXT("Item has errors: %s"), *Errors);
}

// Read properties:
float Weight = Item->Weight;
int32 StackLimit = Item->StackLimit;
EItemType Type = Item->ItemType;

Remaining BP to Create

  • DA_Item_* instances — one per game item (content, not code)
  • WBP_InventoryMenu (49) — uses DA_ItemData properties for display

System 31 — BPC_InventorySystem

C++ Class

Header Source/Framework/Public/Inventory/BPC_InventorySystem.h
Source Source/Framework/Private/Inventory/BPC_InventorySystem.cpp
Parent UActorComponent
Blueprint Child to Create None — attach C++ component directly to player pawn

Setup

  1. Open your player pawn Blueprint
  2. Add Component → BPC_InventorySystem
  3. In component defaults:
    • Grid Width → 8
    • Grid Height → 5
    • Max Weight → 50.0

Usage Pattern

UBPC_InventorySystem* Inv = GetOwner()->FindComponentByClass<UBPC_InventorySystem>();

// Add item:
int32 Added = Inv->AddItem(ItemData, 5);

// Check if we can pick up:
if (Inv->CanAddItem(ItemData, 1))
{
    // Show pickup prompt
}

// Query:
int32 Count = Inv->GetItemCount(ItemData);
TArray<UDA_ItemData*> AllItems = Inv->GetAllItems();
float RemainingWeight = Inv->GetRemainingWeight();

// Organize:
Inv->SortInventory();
Inv->ConsolidateStacks();

// Bind:
Inv->OnInventoryChanged.AddDynamic(this, &UWBP_InventoryMenu::RefreshGrid);
Inv->OnItemAdded.AddDynamic(this, &UWBP_InventoryMenu::OnItemAddedAnim);
Inv->OnWeightChanged.AddDynamic(this, &UWBP_InventoryMenu::UpdateWeightBar);

Key Win vs Blueprint

SortInventory uses Algo::Sort with a C++ lambda — instantaneous. BP array sort requires manual iteration and comparison nodes. AddItem stacks automatically — no BP branching for each stack check.


System 35 — SS_SaveManager

C++ Class

Header Source/Framework/Public/Save/SS_SaveManager.h
Source Source/Framework/Private/Save/SS_SaveManager.cpp
Parent UGameInstanceSubsystem
Blueprint Child None — auto-initialized by UE's subsystem system

No Manual Setup Required

UGameInstanceSubsystem auto-creates when GI_GameFramework initializes. No BP child, no spawn, no BeginPlay needed.

Usage Pattern

USS_SaveManager* Save = UFL_GameUtilities::GetSubsystemSafe<USS_SaveManager>(this);

// Save:
Save->SaveGame(0, TEXT("Chapter 3 — Laboratory"));

// Load:
Save->LoadGame(0);

// Quick save/load:
Save->QuickSave();
Save->QuickLoad();

// Checkpoint:
Save->CreateCheckpoint(CheckpointTag);
Save->LoadCheckpoint(SlotIndex);

// Manifest:
TArray<FSaveSlotInfo> Slots = Save->GetSlotManifest();

// Backup:
Save->BackupAllSaves(TEXT("Pre-Chapter4"));

// Bind:
Save->OnSaveComplete.AddDynamic(this, &UMyClass::OnSaved);
Save->OnLoadComplete.AddDynamic(this, &UMyClass::OnLoaded);

// Bind to manifest updates (when slots change):
Save->OnSaveManifestUpdated.AddDynamic(this, &UWBP_SaveMenu::RefreshSlotList);

Key Win vs Blueprint

C++ uses FArchive for direct binary serialization. BP Save Game/Load Game nodes hide disk errors — C++ catches and reports them. FMemoryWriter/FMemoryReader is faster than BP serialization.


System 72 — BPC_DamageReceptionSystem

C++ Class

Header Source/Framework/Public/Weapons/BPC_DamageReceptionSystem.h
Source Source/Framework/Private/Weapons/BPC_DamageReceptionSystem.cpp
Parent UActorComponent
Blueprint Child to Create None — attach to player and enemy pawns

Setup

  1. Open player pawn Blueprint (and enemy pawn Blueprint)
  2. Add Component → BPC_DamageReceptionSystem
  3. Optionally assign EquipmentConfig Data Asset for armor values

Usage Pattern

UBPC_DamageReceptionSystem* Dmg = GetOwner()->FindComponentByClass<UBPC_DamageReceptionSystem>();

// Apply damage (full pipeline: resistance → armor → shield → health → hit reaction):
float ActualDamage = Dmg->ApplyDamage(
    50.0f,                    // Raw damage
    DamageCauser,             // Who dealt it
    DamageType,               // Framework.Combat.Damage.Physical
    HitLocation,              // Where on the body
    HitDirection              // Direction of the hit
);

// Preview damage (for UI):
float EffectiveResist = Dmg->CalculateResistance(DamageType);

// Bind:
Dmg->OnDamageReceived.AddDynamic(this, &UMyClass::OnDamageReceived);
Dmg->OnStaggered.AddDynamic(this, &UMyClass::OnStaggered);
Dmg->OnKnockedDown.AddDynamic(this, &UMyClass::OnKnockedDown);
Dmg->OnDamageResisted.AddDynamic(this, &UMyClass::OnDamageResisted);

Key Win vs Blueprint

The damage pipeline (resistance → multiplier → flat reduction → shield → health → hit reaction) is a single function call. In BP, this would be a 20+ node chain with multiple branches.


System 128 — SS_EnhancedInputManager

C++ Class

Header Source/Framework/Public/Input/SS_EnhancedInputManager.h
Source Source/Framework/Private/Input/SS_EnhancedInputManager.cpp
Parent UGameInstanceSubsystem
Blueprint Child None — auto-initialized

No Manual Setup Required

Auto-created by UE's subsystem system. No BP child needed.

Usage Pattern

USS_EnhancedInputManager* Input = UFL_GameUtilities::GetSubsystemSafe<USS_EnhancedInputManager>(this);

// Push context (e.g., when player hides):
Input->PushContext(IMC_Hiding, EInputContextPriority::Hiding,
    FGameplayTag::RequestGameplayTag(FName("Framework.Input.Context.Hiding")));

// Pop context (e.g., when player exits hiding):
Input->PopContext(IMC_Hiding);

// Switch to UI mode:
Input->SetInputMode(true, true); // UI mode, show cursor

// Switch back to game mode:
Input->SetInputMode(false, false);

// Rebind key:
Input->RebindKey(IA_Reload, EKeys::R);

// Query:
bool bHidingActive = Input->IsContextActive(HidingTag);
float MoveValue = Input->GetActionValue(IA_Move);
bool bSprinting = Input->IsActionPressed(IA_Sprint);

// Bind:
Input->OnContextPushed.AddDynamic(this, &UMyClass::OnContextPushed);
Input->OnContextPopped.AddDynamic(this, &UMyClass::OnContextPopped);
Input->OnInputModeChanged.AddDynamic(this, &UMyClass::OnInputModeChanged);
Input->OnKeyRebound.AddDynamic(this, &UMyClass::OnKeyRebound);

Remaining BP to Create

  • IA_* Input Action assets (one per gameplay action)
  • IMC_* Input Mapping Context assets (groups of actions)
  • DA_InputMappingProfile (129) — per-platform binding Data Asset

System 130 — BPC_StateManager

C++ Class

Header Source/Framework/Public/Player/BPC_StateManager.h
Source Source/Framework/Private/Player/BPC_StateManager.cpp
Parent UActorComponent
Blueprint Child to Create None — attach C++ component directly

Setup

  1. Open your player pawn Blueprint
  2. Add Component → BPC_StateManager
  3. In component defaults:
    • Gating Table → assign DA_StateGatingTable Data Asset
    • Default Action StateFramework.State.Action.Idle
    • Heart Rate Smooth Speed → 2.0

Usage Pattern

UBPC_StateManager* State = GetOwner()->FindComponentByClass<UBPC_StateManager>();

// THE central query — every gameplay system calls this:
if (State->IsActionPermitted(ActionTag))
{
    // Player can perform this action
}

// Request state change:
EActionRequestResult Result = State->RequestStateChange(NewState, Requester);
switch (Result)
{
    case EActionRequestResult::Granted:        /* proceed */     break;
    case EActionRequestResult::Denied:         /* gated */       break;
    case EActionRequestResult::BlockedByForce: /* death/etc */   break;
    case EActionRequestResult::AlreadyActive:  /* no-op */       break;
}

// Force state (death, cutscene, void space):
State->ForceStateChange(DeathTag, TEXT("Player died"));
// Later, on respawn:
State->RestorePreviousState();

// Vital signs:
float CurrentBPM = State->HeartRateBPM;
EHeartRateTier Tier = State->HeartRateTier; // Resting/Elevated/Stressed/Panic/Critical

// Bind:
State->OnActionStateChanged.AddDynamic(this, &UMyClass::OnActionStateChanged);
State->OnOverlayStateChanged.AddDynamic(this, &UMyClass::OnOverlayStateChanged);
State->OnForceStackPushed.AddDynamic(this, &UMyClass::OnForceStackPushed);
State->OnForceStackPopped.AddDynamic(this, &UMyClass::OnForceStackPopped);
State->OnVitalSignChanged.AddDynamic(this, &UMyClass::OnVitalSignChanged);

Key Win vs Blueprint

IsActionPermitted() is on the hot path — called potentially per-frame by 10+ systems. In C++, it's a native TArray/TMap lookup. In BP, it would be interpretive graph traversal each call. Heart rate smoothing is FMath::FInterpTo in tick — one native call vs BP interpolation nodes.

Remaining BP to Create

  • DA_StateGatingTable (131) — 37 gating rules Data Asset

Quick Reference — C++ Class at a Glance

# C++ Class Parent BP Child? Project Settings Change?
01 UDA_GameTagRegistry UPrimaryDataAsset No — use Data Asset instance Register 11 Data Tables in GameplayTags
02 UFL_GameUtilities UBlueprintFunctionLibrary No — static library None
03 9 UInterfaces UInterface No — implement on actors None
04 UGI_GameFramework UGameInstance YesBP_GameFramework Set as Game Instance Class
05 AGM_CoreGameMode AGameModeBase YesBP_CoreGameMode Set as Default GameMode
06 AGS_CoreGameState AGameStateBase YesBP_CoreGameState Set in GameMode defaults
07 UDA_ItemData UPrimaryDataAsset No — create per-item instances None
31 UBPC_InventorySystem UActorComponent No — add to pawn directly None
35 USS_SaveManager UGameInstanceSubsystem No — auto-created None
72 UBPC_DamageReceptionSystem UActorComponent No — add to pawn/enemy None
128 USS_EnhancedInputManager UGameInstanceSubsystem No — auto-created None
130 UBPC_StateManager UActorComponent No — add to pawn directly None

What "No BP Child" Means

Systems marked "No — add to pawn directly" mean you place the raw C++ component on your Blueprint pawn. The C++ class exposes all configuration via EditAnywhere properties — designers tweak those in the Details panel instead of a Blueprint child.

Systems marked "No — auto-created" are UGameInstanceSubsystems. UE creates them automatically when the GameInstance initializes. No spawning, no placement, no BeginPlay required.


Build Order (Dependency Chain)

1. DA_GameTagRegistry          ← No dependencies (can build first)
2. I_InterfaceLibrary           ← No dependencies
3. FL_GameUtilities             ← Needs GI_GameFramework (forward declare ok)
4. GI_GameFramework             ← Needs DA_GameTagRegistry
5. GM_CoreGameMode              ← Needs GI_GameFramework
6. GS_CoreGameState             ← Needs GI_GameFramework
7. DA_ItemData                  ← No C++ dependencies
8. BPC_InventorySystem          ← Needs DA_ItemData
9. SS_SaveManager               ← Needs GI_GameFramework
10. BPC_DamageReceptionSystem   ← Needs DA_ItemData (EquipmentConfig)
11. SS_EnhancedInputManager     ← No C++ framework deps (EnhancedInput plugin only)
12. BPC_StateManager            ← Needs DA_StateGatingTable (stub)

Blueprint Assets Still Required (Not Converted to C++)

These Blueprint specs remain Blueprint-only. They have full spec files in docs/blueprints/ with Manual Implementation Guides.

GameInstance Subsystems (auto-created, need BP children)

# System BP to Create C++ Status
44 SS_UIManager BP_UIManager C++ available (not in this batch — low priority)
103 SS_AchievementSystem BP_AchievementSystem C++ available (not in this batch)
105 SS_SettingsSystem BP_SettingsSystem C++ available (not in this batch)
132 SS_AudioManager BP_AudioManager C++ available (not in this batch)

Actor Components (attach to pawn)

All 80 BPC_* specs except the 4 converted above remain Blueprint-only. Create BP children, attach to pawn.

Widgets (all 14 remain Blueprint — UMG is designed for BP)

# System
45-57 All WBP_* widgets (HUD, menus, notifications, etc.)
112-114 Credits, Debug, Splash screens

Data Assets (create instances, not children)

# System
115-127, 129, 131, 134-135 All DA_* Data Asset definitions — create instances per content item

Actors (create BP children)

# System
19, 20, 25, 37, 67, 69, 80, 81, 133 All BP_* actors

Interfaces

| 17 | I_HidingSpot — remains BP interface (simple, no C++ advantage) | | 36 | I_Persistable — already in C++ I_InterfaceLibrary.h |


C++ Integration Guide v1.0 — Companion to Source/Framework/ source files.