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

189 lines
9.6 KiB
Markdown

# 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 Names``Get 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<Data Table> → nested `ForEachLoop``Get 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.*