Refactor GameplayTag documentation and implementation

- Updated references from GI_GameTagRegistry to DA_GameTagRegistry in architecture overview and implementation patterns documentation.
- Added new Blueprint specification for GI_StarterGameInstance, detailing its purpose, configuration, and integration pattern.
- Introduced DA_GameTagRegistry Blueprint specification, centralizing GameplayTag management and providing functions for tag validation and logging.
- Created documentation for the Starter GameInstance, outlining its role in the project setup and how other systems can integrate with it.
This commit is contained in:
Lefteris Notas
2026-05-20 14:31:52 +03:00
parent 3023ad3555
commit fee12b115f
17 changed files with 927 additions and 423 deletions

View File

@@ -0,0 +1,355 @@
# GI_StarterGameInstance — Blueprint Specification
> **Asset Type:** Game Instance (derives from `UGameInstance`)
> **UE Version:** 5.55.7
> **Category:** 00-Project-Setup / Starter
> **Build Phase:** Pre-Phase 0 — Project Initialization
> **Dependencies:** `DA_GameTagRegistry` (01), 11 per-category Data Tables, GameplayTags plugin
---
## 1. Purpose
A minimal, ready-to-use GameInstance Blueprint that serves as the project's **immediate** entry point. Set this as your `Game Instance Class` in Project Settings to get tag validation and framework bootstrapping working on day one. It loads `DA_GameTagRegistry`, validates that all 11 Data Tables are registered, and broadcasts `OnFrameworkReady` when initialization completes.
**This is intentionally simple.** As the project matures, replace it with `GI_GameFramework` (04) which adds full game-phase management, subsystem ownership, platform init, and save-slot orchestration. All systems that bind to `OnFrameworkReady` will continue working with either GameInstance.
---
## 2. Class Settings
| Setting | Value |
|---------|-------|
| **Parent Class** | `GameInstance` |
| **Blueprint Type** | Game Instance |
| **Asset Path** | `/Game/Framework/Core/GI_StarterGameInstance` |
| **Is Abstract** | No |
**UE5 Setup:** `Project Settings → Maps & Modes → Game Instance Class``GI_StarterGameInstance`
---
## 3. Enums
None. No custom enums are defined in this system.
---
## 4. Structs
None. No custom structs are defined in this system.
---
## 5. Variables
### Configuration (Instance Editable)
| Name | Type | Default | Category | Description |
|------|------|---------|----------|-------------|
| `TagRegistry` | `DA_GameTagRegistry` (Object Reference) | *Assigned in Class Defaults* | Config | Hard reference to the `DA_GameTagRegistry` Data Asset |
| `bValidateTagsOnInit` | `Boolean` | `true` | Config | If true, calls `DA_GameTagRegistry.GetAllRegisteredTags()` during `Event Init` and logs tag count |
| `bLogTagsOnInit` | `Boolean` | `false` | Debug | If true, calls `DA_GameTagRegistry.LogAllTags()` after validation (Editor-only; heavy logging) |
### Internal (Private)
| Name | Type | Default | Category | Description |
|------|------|---------|----------|-------------|
| `bFrameworkInitialized` | `Boolean` | `false` | State | Set to `true` after `Event Init` completes successfully |
---
## 6. Functions
### Public Functions
#### `GetTagRegistry()` → `DA_GameTagRegistry` *(Blueprint Pure)*
- **Description:** Returns the cached `TagRegistry` reference. Returns `None` if not yet loaded.
- **Parameters:** None
- **Flow:**
1. Return `TagRegistry` variable
#### `IsFrameworkReady()` → `Boolean` *(Blueprint Pure)*
- **Description:** Returns whether the framework has completed initialization. Systems should check this before querying tag-dependent services.
- **Parameters:** None
- **Flow:**
1. Return `bFrameworkInitialized`
### Protected / Private Functions
#### `ValidateFrameworkTags()` *(Blueprint Callable, Private)*
- **Description:** Loads the tag registry, counts registered tags, and logs warnings if zero tags are found. Called automatically during `Event Init`.
- **Parameters:** None
- **Flow:**
1. `IsValid(TagRegistry)`? → False: Print Error "TagRegistry not assigned!" → Return
2. Call `TagRegistry.GetAllRegisteredTags()``AllTags` (Array\<GameplayTag\>)
3. `Array Length(AllTags) == 0`?
- True: Print Warning "No Gameplay Tags registered! Check Project Settings → GameplayTags → Gameplay Tag Table List. All 11 Data Tables must be added."
- False: Print String "DA_GameTagRegistry initialized: {Array Length} tags registered across 11 Data Tables."
4. If `bLogTagsOnInit`: Call `TagRegistry.LogAllTags()`
---
## 7. Event Dispatchers
| Dispatcher | Parameters | Bind Access | Description |
|------------|-----------|-------------|-------------|
| `OnFrameworkReady` | — | Public | Fires after `Event Init` completes and tag validation passes. Other systems bind to this to defer initialization until the framework is ready. |
| `OnFrameworkInitFailed` | `ErrorReason: String` | Public | Fires if `TagRegistry` is invalid or zero tags are found during init. Systems should handle gracefully — show error UI, disable gameplay. |
---
## 8. Overridden Events
### Event: `Event Init`
- **Description:** UE5's GameInstance initialization event. Fires once when the game starts, before any level loads. This is where framework bootstrapping happens.
- **Flow:**
1. Call `Parent: Event Init` (important — don't skip)
2. Print String: "GI_StarterGameInstance: Init started"
3. `Branch: bValidateTagsOnInit?`
- False → Print String "Tag validation skipped (bValidateTagsOnInit = false)"
- True → Call `ValidateFrameworkTags()`
4. `Branch: IsValid(TagRegistry)?`
- False → Print Error "DA_GameTagRegistry reference is invalid!" → Call `OnFrameworkInitFailed("TagRegistry not assigned or invalid")` → Return
- True → Continue
5. Set `bFrameworkInitialized = true`
6. Call `OnFrameworkReady` (broadcast to all bound listeners)
7. Print String: "GI_StarterGameInstance: Init complete — OnFrameworkReady broadcast"
---
## 9. Blueprint Graph Logic Flow
```mermaid
flowchart TD
A[Event Init] --> B[Call Parent: Event Init]
B --> C{ bValidateTagsOnInit? }
C -->|True| D[Call ValidateFrameworkTags]
C -->|False| E[Skip validation]
D --> F{ IsValid TagRegistry? }
F -->|False| G[Print Error<br>Broadcast OnFrameworkInitFailed]
F -->|True| H[Set bFrameworkInitialized = true]
H --> I[Broadcast OnFrameworkReady]
I --> J[Print 'Init Complete']
```
### ValidateFrameworkTags Flow
```mermaid
flowchart TD
A[ValidateFrameworkTags] --> B{ IsValid TagRegistry? }
B -->|False| C[Print Error: TagRegistry not assigned]
B -->|True| D[Call GetAllRegisteredTags → AllTags]
D --> E{ Array Length == 0? }
E -->|True| F[Print Warning: No tags registered]
E -->|False| G[Print: N tags registered]
G --> H{ bLogTagsOnInit? }
H -->|True| I[Call LogAllTags]
H -->|False| J[Return]
I --> J
F --> J
C --> J
```
---
## 10. Communication Matrix
| Source | Target | Method | Direction | Data |
|--------|--------|--------|-----------|------|
| `GI_StarterGameInstance` | `DA_GameTagRegistry` | Direct function call | Outbound | Calls `GetAllRegisteredTags()`, `LogAllTags()`, `ValidateTag()` |
| `GI_StarterGameInstance` | All bound systems | `OnFrameworkReady` dispatcher | Outbound broadcast | No data — listeners query `IsFrameworkReady()` |
| `GI_StarterGameInstance` | All bound systems | `OnFrameworkInitFailed` dispatcher | Outbound broadcast | `ErrorReason: String` |
| Any system | `GI_StarterGameInstance` | `GetGameInstance()` → Cast | Inbound query | Systems call `IsFrameworkReady()` before initialization |
---
## 11. Validation Checklist
- [ ] `GI_StarterGameInstance` set as `Game Instance Class` in `Project Settings → Maps & Modes`
- [ ] `TagRegistry` variable assigned to `DA_GameTagRegistry` Data Asset in Class Defaults
- [ ] All 11 Data Tables registered in `Project Settings → GameplayTags → Gameplay Tag Table List`
- [ ] On PIE (Play In Editor): output log shows "N tags registered across 11 Data Tables"
- [ ] On PIE with `bLogTagsOnInit = true`: all tag names printed to output log
- [ ] If `TagRegistry` is unassigned: error prints and `OnFrameworkInitFailed` fires (test by clearing the variable)
- [ ] Other systems successfully bind to `OnFrameworkReady` and defer their init
- [ ] Edge case: 0 tags in Data Tables → warning prints, `OnFrameworkInitFailed` does NOT fire (empty tables are a warning, not a failure)
---
## 12. Reuse Notes
- **Replacement path:** When you are ready for the full `GI_GameFramework` (04), simply change the `Game Instance Class` in Project Settings. All systems that bind to `OnFrameworkReady` on either GameInstance will work — `GI_GameFramework` includes the same dispatcher.
- **Project-specific init:** Add custom initialization (achievement platform, analytics, save migration) after the `OnFrameworkReady` broadcast in `Event Init`.
- **Tag registry is a Data Asset, not a subsystem:** You must manually assign the `TagRegistry` reference in Class Defaults. It is NOT auto-discovered.
- **Multi-platform:** On consoles, `Event Init` fires before any level loads — same as PC. No platform-specific code is needed.
---
## 13. Manual Implementation Guide
> **For human implementer:** Follow these steps to build `GI_StarterGameInstance` in UE5 Blueprints. This is the FIRST Blueprint you should create — it enables tag validation for all other systems.
### 13.1 Class Setup
1. Right-click in Content Browser → **Blueprint Class**
2. Search for parent class: `GameInstance`
3. Name: `GI_StarterGameInstance`
4. Save to: `Content/Framework/Core/`
5. Open **Project Settings → Maps & Modes** → Set `Game Instance Class` to `GI_StarterGameInstance`
### 13.2 Variables
Add to Class Defaults:
| Variable | Type | Instance Editable | Default | Category |
|----------|------|------------------|---------|----------|
| `TagRegistry` | `DA_GameTagRegistry` (Object Reference) | ✓ | *Select `DA_GameTagRegistry` asset* | Config |
| `bValidateTagsOnInit` | `Boolean` | ✓ | `true` | Config |
| `bLogTagsOnInit` | `Boolean` | ✓ | `false` | Debug |
| `bFrameworkInitialized` | `Boolean` | ✗ (Private) | `false` | State |
**⚠️ Important:** For `TagRegistry`, use the type `DA_GameTagRegistry` (your specific Data Asset Blueprint class, NOT the generic `PrimaryDataAsset`). Compile `DA_GameTagRegistry` first so it appears in the type dropdown.
### 13.3 Event Dispatchers
Create two Event Dispatchers in the **My Blueprint** panel:
1. `OnFrameworkReady` — no parameters
2. `OnFrameworkInitFailed` — add one input parameter:
- `ErrorReason` (String)
### 13.4 Override Event Init
1. In the **My Blueprint** panel, hover over **Functions** → click **Override** → select `Event Init`
2. Build the following graph:
```
[Event Init]
Step 1: Call "Parent: Event Init" (right-click event node → "Add Call to Parent")
Step 2: Print String: "GI_StarterGameInstance: Init started"
→ Text (Format Text): "GI_StarterGameInstance: Init started"
Step 3: Branch (Condition: bValidateTagsOnInit)
True → Call ValidateFrameworkTags (see 13.5)
False → Print String: "Tag validation skipped (bValidateTagsOnInit = false)"
Step 4: IsValid(TagRegistry) → Branch
False:
→ Print String: "DA_GameTagRegistry reference is invalid!"
→ Call OnFrameworkInitFailed (ErrorReason = "TagRegistry not assigned or invalid")
→ Return Node
True: Continue
Step 5: Set bFrameworkInitialized = true
Step 6: Call OnFrameworkReady (no params)
Step 7: Print String: "GI_StarterGameInstance: Init complete — OnFrameworkReady broadcast"
```
**Nodes to Search:** `Event Init`, `Add Call to Parent`, `Print String`, `Format Text`, `Branch`, `IsValid`, `Set`, `Call OnFrameworkReady`, `Call OnFrameworkInitFailed`
### 13.5 Implement ValidateFrameworkTags
Create a new function: **BlueprintCallable**, Private, named `ValidateFrameworkTags`.
```
[Function: ValidateFrameworkTags] (BlueprintCallable, Private)
Step 1: IsValid(TagRegistry) → Branch
False: Print String "TagRegistry not assigned in GI_StarterGameInstance!" → Return
True: Continue
Step 2: Call TagRegistry → GetAllRegisteredTags() → store in "AllTags" (Array<GameplayTag>)
Step 3: Array Length(AllTags) → store in "TagCount" (Integer)
Step 4: Branch (Condition: TagCount == 0)
True: Print String (Color: Yellow): "WARNING: No Gameplay Tags registered! Check Project Settings → GameplayTags → Gameplay Tag Table List. All 11 Data Tables must be added."
False: Print String (Format Text): "DA_GameTagRegistry initialized: {TagCount} tags registered across 11 Data Tables."
Step 5: Branch (Condition: bLogTagsOnInit)
True: Call TagRegistry → LogAllTags()
False: Continue (no action)
Step 6: Return
```
**Nodes to Search:** `IsValid`, `GetAllRegisteredTags`, `Array Length`, `Branch`, `Print String`, `Format Text`, `LogAllTags`
### 13.6 Implement GetTagRegistry
Create a new function: **BlueprintPure**, Public, named `GetTagRegistry`.
```
[Function: GetTagRegistry] → DA_GameTagRegistry (BlueprintPure)
Return TagRegistry
```
### 13.7 Implement IsFrameworkReady
Create a new function: **BlueprintPure**, Public, named `IsFrameworkReady`.
```
[Function: IsFrameworkReady] → Boolean (BlueprintPure)
Return bFrameworkInitialized
```
### 13.8 How Other Systems Bind to OnFrameworkReady
In any other Blueprint that needs framework services (tag validation, subsystems, etc.):
```
[Event BeginPlay]
Step 1: Get Game Instance → Cast to GI_StarterGameInstance → Store as "GameInstance"
Step 2: Branch: IsValid(GameInstance)?
True:
→ Branch: GameInstance → IsFrameworkReady()?
True: Call "OnFrameworkReadyHandler" immediately (already initialized)
False: Bind "OnFrameworkReadyHandler" to GameInstance.OnFrameworkReady
False: Print Warning "GI_StarterGameInstance not found!"
```
**Custom Event: OnFrameworkReadyHandler**
```
[Custom Event: OnFrameworkReadyHandler]
Step 1: Unbind from GameInstance.OnFrameworkReady (if bound — prevents double-fire)
Step 2: ... proceed with system-specific initialization ...
```
### 13.9 Quick Node Reference
| Node | Where to Find | Used For |
|------|---------------|----------|
| `Event Init` | Override in My Blueprint → Functions | GameInstance startup |
| `Get Game Instance` | Right-click → "Get Game Instance" | Any Blueprint that needs the GameInstance |
| `Cast to GI_StarterGameInstance` | Right-click → "Cast to GI_StarterGameInstance" | Type-safe access to framework functions |
| `IsValid` | Right-click → "IsValid" | Null-checking object references |
| `Bind Event to OnFrameworkReady` | Right-click on dispatcher → "Bind Event" | Deferred initialization |
| `Unbind Event from OnFrameworkReady` | Right-click on dispatcher → "Unbind Event" | Clean up after handler fires |
---
## 14. Blueprint Build Checklist
- [ ] Create `GI_StarterGameInstance` Blueprint (Parent: `GameInstance`)
- [ ] Set as `Game Instance Class` in `Project Settings → Maps & Modes`
- [ ] Create `DA_GameTagRegistry` Data Asset first (required for `TagRegistry` variable type)
- [ ] Add variable `TagRegistry` (type: `DA_GameTagRegistry`) and assign the Data Asset
- [ ] Add variable `bValidateTagsOnInit` (Boolean, default `true`)
- [ ] Add variable `bLogTagsOnInit` (Boolean, default `false`)
- [ ] Add variable `bFrameworkInitialized` (Boolean, default `false`, Private)
- [ ] Create Event Dispatcher `OnFrameworkReady` (no params)
- [ ] Create Event Dispatcher `OnFrameworkInitFailed` (1 param: `ErrorReason` String)
- [ ] Override `Event Init` — add Call to Parent, validation branch, dispatcher broadcasts
- [ ] Implement `ValidateFrameworkTags()` — validate registry, count tags, optional log
- [ ] Implement `GetTagRegistry()` (BlueprintPure) — return TagRegistry reference
- [ ] Implement `IsFrameworkReady()` (BlueprintPure) — return bFrameworkInitialized
- [ ] Compile and test: PIE → output log shows "DA_GameTagRegistry initialized: N tags"
- [ ] Test error path: clear `TagRegistry` variable → `OnFrameworkInitFailed` fires
- [ ] Test with `bLogTagsOnInit = true` → all tags printed to output log
- [ ] Verify other systems can bind to `OnFrameworkReady` and defer init correctly
---
## 15. Multiplayer Networking
**Replication: None needed.** The GameInstance is a client-only singleton — each client has its own instance. The `DA_GameTagRegistry` Data Asset loads identically from disk on all clients and servers. Event Dispatchers (`OnFrameworkReady`, `OnFrameworkInitFailed`) fire locally on each instance.
**Authority: N/A.** No runtime state changes. Tag data is read-only configuration.
**Multiplayer Note:** In a networked game, `Event Init` fires on both server and each client's GameInstance. Tag validation runs independently on each — which is correct, since Data Tables and GameplayTags must be identical across all instances for networked tag replication to function.