142 lines
5.8 KiB
Markdown
142 lines
5.8 KiB
Markdown
# U-Tad UI Project
|
|
|
|
**English** | **[Leer en Español](README-es.md)**
|
|
|
|
---
|
|
|
|
## Skill Tree System Implementation
|
|
|
|
### Overview
|
|
A complete skill tree system with node-based progression, prerequisite validation, visual connection lines, and data-driven configuration.
|
|
|
|

|
|
|
|
---
|
|
|
|
## Architecture: Blueprint Decision
|
|
|
|
### Blueprint Implementation
|
|
**Components:** `WBP_SkillTree`, `WBP_SkillNode`, `WBP_SkillNodeTooltip`
|
|
|
|
**Reasoning:**
|
|
- **Iteration speed**: UI layout and styling require rapid visual iteration
|
|
- **Designer-friendly**: Artists/designers can modify UI without C++ knowledge
|
|
|
|

|
|
|
|
---
|
|
|
|
## Core Systems
|
|
|
|
### 1. Data Layer (`SkillTreeTypes.h`)
|
|
**Structures:**
|
|
- `FSkillNodeData`: Skill definition row for skill data table (name, cost, prerequisites, effects, starting flag)
|
|
- `FSkillNodeRuntime`: Runtime state wrapper
|
|
- `ESkillNodeState`: State enum (Locked, Available, Selected, Purchased)
|
|
|
|
**Decision**: Data Table-driven design allows non-programmers to configure skills without recompiling.
|
|
|
|

|
|
|
|
### 2. Logic Layer (`SkillTreeComponent`)
|
|
**Responsibilities:**
|
|
- Skill tree initialization from DataTable
|
|
- State management (prerequisites, affordability checks)
|
|
- Selection validation and purchase confirmation
|
|
- Starting skills auto-purchase
|
|
- Skill point management
|
|
- Effect application hooks
|
|
|
|
**Key Features:**
|
|
- **Purchase order sorting**: Ensures prerequisites are purchased before dependents
|
|
- **Cascade deselection**: Removing a prerequisite deselects dependent skills
|
|
- **Starting skills**: Marked in DataTable, auto-purchased at init, preserved on reset
|
|
- **Stat aggregation**: Provides `GetTotal[Stat]Bonus()` functions to sum all purchased skills' bonuses
|
|
|
|
### 3. Stats Integration Layer (`CharacterStatsComponent`)
|
|
**Responsibilities:**
|
|
- Automatic stat calculation from purchased skills
|
|
- Character stat management (Health, Damage, Speed)
|
|
- Real-time updates when skills are purchased
|
|
- Movement speed integration
|
|
|
|
**How it works:**
|
|
- Finds SkillTreeComponent on same actor at BeginPlay
|
|
- Listens to `OnSkillPurchased` event
|
|
- Iterates all purchased skills, sums flat + percentage bonuses
|
|
- Applies formula: `FinalStat = Base + FlatBonus + (Base * PercentBonus / 100)`
|
|
- Auto-updates CharacterMovementComponent speed
|
|
- Broadcasts stat change events for UI updates
|
|
|
|
**Decision**: Separate stats component keeps concerns separated - SkillTreeComponent handles progression, CharacterStatsComponent handles stat application. Makes both reusable independently.
|
|
|
|
### 4. Visualization Layer (`SkillTreeConnectionsWidget`)
|
|
**Responsibilities:**
|
|
- Automatic line drawing between prerequisite nodes (You only need to place nodes in the UI!)
|
|
- Dynamic line coloring based on skill states
|
|
- Event-driven refresh on state changes
|
|
|
|
**Technical Approach:**
|
|
- **Generic search**: Works with any widget hierarchy so designers/artist are not limited when creating the skill tree widget (Canvas, Overlay, Grid)
|
|
- **NativePaint override**: Direct Slate rendering for performance
|
|
- **Delegate binding**: Auto-refreshes when skills change state
|
|
|
|
**Decision**: Single self-contained widget eliminates manual line management and Blueprint complexity.
|
|
|
|
<p align="center">
|
|
<img src="Docs/Images/Lines_1.png" alt="Lines 1" width="45%"/>
|
|
<img src="Docs/Images/Lines_2.png" alt="Lines 1" width="45%"/>
|
|
</p>
|
|
|
|
### 5. UI Layer (Blueprints)
|
|
**WBP_SkillNode & WBP_SkillNodeTooltip:**
|
|
- Displays skill icon, state, cost
|
|
- Handles click events (select/deselect)
|
|
- Stores SkillID for runtime lookup
|
|
- Custom tooltip support to display skill details
|
|
- Real time state updates via event binding allows real-time visual feedback
|
|
|
|
**WBP_SkillTree:**
|
|
- Contains manually-placed skill nodes
|
|
- References SkillTreeComponent
|
|
- Hosts SkillTreeConnectionsWidget which draws lines between nodes automatically
|
|
- Binds to component events for UI updates
|
|
|
|
**Decision**: Manual node placement allows custom layouts (linear, radial, branching) per designer preference.
|
|
|
|
---
|
|
|
|
## Key Design Decisions
|
|
|
|
### 1. Skill prerequisites in DataTable
|
|
**Alternative**: Hard-coded in C++ or DataAssets references
|
|
**Chosen**: DataTable array
|
|
**Reason**: Designers can modify skill dependencies without programmer intervention and without recompiling
|
|
|
|
### 2. Component vs Subsystem
|
|
**Alternative**: Game Instance Subsystem
|
|
**Chosen**: Actor Component
|
|
**Reason**: Supports multiple skill trees per player (e.g., combat tree, crafting tree) and easier save/load integration
|
|
|
|
### 3. Single Connections Widget
|
|
**Alternative**: Individual line widgets per connection with manual management
|
|
**Chosen**: One widget draws all lines automatically
|
|
**Reason**: Eliminates array management, better performance, automatic coordinate handling
|
|
|
|
### 4. Separate Stats Component
|
|
**Alternative**: Apply stats directly in SkillTreeComponent
|
|
**Chosen**: Separate CharacterStatsComponent
|
|
**Reason**: Separation of concerns - SkillTreeComponent is reusable for any progression system, CharacterStatsComponent specifically handles character stats. Allows skill trees without stat bonuses, or stats without skill trees.
|
|
|
|
---
|
|
|
|
## Technical Highlights
|
|
|
|
- **Event-driven architecture**: Component broadcasts state changes, UI responds automatically
|
|
- **State machine validation**: Prevents invalid transitions (e.g., can't select locked skills)
|
|
- **Automatic stat application**: CharacterStatsComponent listens to skill purchases, recalculates stats, applies to character
|
|
- **Geometry-aware rendering**: Lines adapt to any widget positioning system
|
|
- **Data-driven configuration**: Zero code changes and no need to compile for new skills or tree layouts
|
|
- **Reset functionality**: Refunds non-starting skills, maintains starting points
|
|
- **Modular design**: Skill progression, stats, and visualization are independent
|