Files
UE5-Modular-Game-Framework/docs/architecture/blueprint-limitations-workarounds.md
Lefteris Notas 209f24a0f8 Refactor Gameplay Tags: Split DT_ProjectTags.csv into 11 per-category Data Tables
- Removed DT_ProjectTags.csv and migrated tags into separate Data Tables:
  - DT_Tags_Player.csv (35 tags)
  - DT_Tags_Interaction.csv (37 tags)
  - DT_Tags_Item.csv (28 tags)
  - DT_Tags_Narrative.csv (55 tags)
  - DT_Tags_AI.csv (24 tags)
  - DT_Tags_Save.csv (25 tags)
  - DT_Tags_Environment.csv (35 tags)
  - DT_Tags_Combat.csv (28 tags)
  - DT_Tags_State.csv (43 tags)
  - DT_Tags_Audio.csv (29 tags)
  - DT_Tags_Achievement.csv (22 tags)

- Updated INDEX.md to reflect new structure and deprecated DT_ProjectTags.csv.
- Enhanced documentation in 01-core-foundation.md regarding tag-driven architecture.
2026-05-19 19:20:40 +03:00

9.6 KiB

UE5 Blueprint Limitations & Workarounds — Modular Game Framework

Version: 1.0 | Generated: 2026-05-19

This document catalogs all UE5 engine functions that are C++ only (not exposed to Blueprints) which the framework's specification files reference, and provides 100% Blueprint workarounds for each.


1. GameplayTags Limitations

1.1 Get All Gameplay Tags (C++ Only)

Engine Function: UGameplayTagsManager::Get().RequestAllGameplayTags()
UE5 Node: Does NOT exist in Blueprint
Files Affected: 01_GI_GameTagRegistry.md, any system that needs to enumerate all tags

Blueprint Workaround — Data Table Proxy (Multi-Table):

  1. Create 11 per-category Data Tables with Row Structure = GameplayTagTableRow (see docs/blueprints/01-core/data-tables/)
  2. Populate each with its category's tags (mirrors DefaultGameplayTags.ini)
  3. Register ALL tables in Project Settings → GameplayTags → Gameplay Tag Table List
  4. In Blueprint: use outer ForEachLoop over Array<Data Table> + inner ForEachLoop over Get Data Table Row NamesGet Data Table Row → extract Tag field
  5. This provides a complete tag list without C++

Trade-off: Manual maintenance. Adding new tags requires updating both the .ini file AND the Data Table. Mitigation: use ExportTagNamespace() to audit for discrepancies.

1.2 RequestGameplayTag(String) → GameplayTag (C++ Only)

Engine Function: UGameplayTagsManager::Get().RequestGameplayTag(FName)
UE5 Node: Not directly available. The closest BP node is Make Literal Gameplay Tag.

Blueprint Workaround — Multiple options:

Option A: Make Literal Gameplay Tag — creates a GameplayTag from a literal string at compile time. Works only if the tag exists in the tag table. Option B: Is Gameplay Tag Valid — for validation only (returns boolean).
Option C: Get Gameplay Tag from Name (available in some UE5 versions via GameplayTagsBlueprintLibrary).

Recommendation: For ValidateTag() in DA_GameTagRegistry, use Is Gameplay Tag Valid. For runtime tag creation from strings, use Make Literal Gameplay Tag with fallback validation.

1.3 UGameplayTagsManager::Get() Singleton (C++ Only)

Engine Pattern: UGameplayTagsManager::Get() returns the singleton.
UE5 Node: Not available. The manager is accessed implicitly through GameplayTags Blueprint nodes.

Blueprint Workaround: Never reference the manager directly. Use the Blueprint nodes listed above. All tag operations (match, compare, validate) have Blueprint equivalents.


2. Subsystem Access Limitations

2.1 Static Function Library Accessor Pattern (Requires C++ for Clean Implementation)

Pattern: FL_GameUtilities::GetUIManager(), FL_GameUtilities::GetInputManager()
Issue: BlueprintFunctionLibrary static functions require C++ implementation for the static accessor pattern. In pure Blueprint, you cannot create a truly static accessor with clean syntax.

Blueprint Workaround:

Instead of FL_GameUtilities::GetUIManager(), use:

Get Game Instance → Get Subsystem (SS_UIManager Class)

OR create a Blueprint Macro Library with a macro that wraps the subsystem lookup.

Files Affected: 02_FL_GameUtilities.md, 44_SS_UIManager.md, 128_SS_EnhancedInputManager.md

Recommendation: For a pure BP framework, document the direct Get Game Instance → Get Subsystem pattern. The FL_GameUtilities static accessors can be kept as documentation of the intent, but the implementation guide should show the direct BP node path.


3. Data Asset Limitations

3.1 OnAssetLoaded / BeginPlay on Data Assets (Not Available)

Engine Behavior: UPrimaryDataAsset does not have BeginPlay, Tick, or event graphs. It's a pure data container.
Files Affected: 01_GI_GameTagRegistry.md, all DA_* specs

Blueprint Workaround: Move initialization and validation logic to an owning system:

  • GameInstance (GI_GameFramework.Init()) — load and validate Data Assets at game startup
  • Subsystem (BPC_StateManager.BeginPlay()) — validate configuration during component init
  • Editor Utility — create an Editor Utility Widget/Blueprint for pre-game validation

Pattern:

[In GI_GameFramework.Init()]
  Load DA_GameTagRegistry (hard reference)
  Call DA_GameTagRegistry.ValidateAllTags()
  If failed → Print Error, optionally halt

3.2 FPrimaryAssetId / FPrimaryAssetType in Variables (Blueprint Types Exist)

Engine Types: FPrimaryAssetId, FPrimaryAssetType
Blueprint Equivalent: Primary Asset Id (variable type), Primary Asset Type (variable type)

Workaround: Use the Blueprint variable types Primary Asset Id and Primary Asset Type. The Async Load Primary Asset node works in Blueprint. Asset Manager configuration (types, labels) is done in Project Settings → Asset Manager or DefaultGame.ini.

Files Affected: 07_DA_ItemData.md, 118_DA_DataAssetArchitecture.md, 119_DA_EncounterData.md, 123_DA_ObjectiveData.md, 27_BPC_CollectibleTracker.md

3.3 AssetManager / StreamableManager Async Loading (Blueprint Nodes Exist)

Blueprint Nodes Available:

  • Async Load Primary Asset — async loading with callback
  • Get Asset Manager — returns the Asset Manager subsystem
  • Get Primary Asset Id List — enumerates registered assets

⚠️ Limitation: UAssetManager::GetPrimaryAssetPath() and some query functions are C++ only. For pure BP, use Async Load Primary Asset by Primary Asset Id.


4. Animation & Physics Limitations

4.1 Motion Warping Target Calculation (Blueprint Available)

UE5 Node: Add Motion Warping Target, Calculate Motion Warping Target — these exist in Blueprint.

Files Affected: 21_BPC_ContextualTraversalSystem.md — no workaround needed, standard BP nodes available.

4.2 Physics Constraint Component Creation at Runtime (Blueprint Available)

UE5 Node: Add Physics Constraint Component, Set Constrained Components — available in Blueprint.

Files Affected: 22_BPC_PhysicsDragSystem.md — no workaround needed.


5. Input System Limitations

5.1 Enhanced Input Subsystem Access (Blueprint Available)

UE5 Node: Get Enhanced Input Local Player Subsystem, Add Mapping Context, Remove Mapping Context — available in Blueprint.

Files Affected: 128_SS_EnhancedInputManager.md — no workaround needed.


6. Debug & Development Limitations

6.1 DO_CHECK / Preprocessor Stripping for Shipping (Requires C++ or Project Setting)

Issue: C++ functions can use #if !UE_BUILD_SHIPPING to strip code from shipping builds. Blueprint functions can't do this natively.

Blueprint Workaround:

Option A: Editor-only Blueprint nodes — some nodes have an "Editor Only" checkbox. Mark debug functions as editor-only.
Option B: Is Editor Build branch — branch on Is Editor or development build check before executing debug logic.
Option C: Debug object channel — create a separate Blueprint with all debug logic; don't include it in shipping builds.

Files Affected: 02_FL_GameUtilities.md, 107_BPC_DevCheatManager.md, 113_WBP_DebugMenu.md

Recommendation: Use Is Editor Build branch before all debug logic. Accept that some debug code will exist in shipping builds but be inactive at runtime.


7. Quick Reference: Node Availability Map

Engine C++ Function Available in BP? BP Node Name Workaround Needed?
UGameplayTagsManager::RequestAllGameplayTags() No N/A Yes — Data Table proxy
UGameplayTagsManager::RequestGameplayTag() ⚠️ Partial Make Literal Gameplay Tag Use Is Gameplay Tag Valid for validation
UGameplayTagsManager::Get() No N/A Never needed — use BP tag nodes
GetSubsystem<T>() Yes Get Subsystem (Class) No
GetGameInstance() Yes Get Game Instance No
UAssetManager::Get() Yes Get Asset Manager No
StreamableManager::RequestAsyncLoad() Yes Async Load Primary Asset No
CharacterMovementComponent functions Yes Various BP nodes No
PlayerCameraManager functions Yes Get Player Camera Manager No
Enhanced Input functions Yes Get Enhanced Input Local Player Subsystem No
Physics Constraint functions Yes Add Physics Constraint Component No
#if !UE_BUILD_SHIPPING preprocessor No N/A Use Is Editor Build branch

8. Implementation Rules for BP-Only Framework

When writing or updating Blueprint spec files, follow these rules to avoid C++-only references:

  1. Never reference UGameplayTagsManager::Get() — use Get Tag Display Name, Is Gameplay Tag Valid, Make Literal Gameplay Tag.
  2. Never reference Get All Gameplay Tags — use the multi-table Data Table proxy pattern (Array → nested ForEachLoopGet Data Table Row).
  3. Never use FPrimaryAssetId as a type name — use Primary Asset Id (Blueprint type).
  4. Never use TSoftObjectPtr as a type name — use Soft Object Reference (Blueprint type).
  5. Never put logic in Data Assets — move initialization/validation to GameInstance, Subsystem, or Editor Utility.
  6. Never use C++ include guards or preprocessor — use Is Editor Build for conditional logic.
  7. Prefer Get Game Instance → Get Subsystem(Class) over static helper functions for subsystem access.

Blueprint Limitations & Workarounds v1.0 — Maintained alongside framework specs. Update when new engine limitations are discovered.