Loading
Group Project
HardDriverz

HardDriverz is an arcade racing game where players customize karts to compete through twisty, futuristic tracks that defy gravity. Pick up unique power-ups to get ahead of other racers as you compete to be the fastest on the circuit.

Gameplay Trailer

HardDriverz Official Gameplay Trailer

My Contributions

I served as the UI Systems Programmer on this team project, solely responsible for the in-game HUD framework and the global event bus that powers it. My work spanned two major areas:

  • Event-Driven HUD Framework (UMG_HudPannel, BPC_KartHud). Designed and implemented a split-screen-aware HUD system that dynamically rearranges layout, anchors, and widget instances based on the active player count. Each HUD element (Lap Counter, Pickup, Ranking, Timer) is a self-contained, event-receiving component with its own lifecycle.
  • Blueprint-Based Global Event Bus (BP_EventModule, TABLE_RegisterEvent). Architected a centralized message bus that decouples gameplay systems from UI. Designers register new events via a DataTable row. No code changes required. Any system can broadcast or subscribe without holding direct references to other actors.
HardDriverz HUD overall demo
Complete HUD system overview showing all widget components working together during gameplay.
0:00
/0:00
Full HUD system walkthrough demonstrating real-time event-driven updates across all widget components.

Technical Overview

The core challenge in HardDriverz was maintaining UI performance and layout integrity across diverse player counts in a high-speed racing game. I architected a data-driven UI framework that leverages an asynchronous global message bus to decouple gameplay logic from high-frequency UI updates.

Instead of traditional polling or hard-coded UI references, I implemented a “Push” architecture where the game state manages its own events, and the HUD acts as a reactive listener.

Architectural Highlight

I designed the communication layer through a centralized Event Module, allowing every component, from weapon pickups to lap updates, to broadcast state changes without needing a direct reference to the UI widgets.

graph TD
subgraph Gameplay Logic
P[Player Pawn] --> BPC_KH[BPC_KartHud Component]
P --> BPC_L[BPC_LapCounter Logic]
P --> BPC_P[Pickup System]
end

subgraph Messaging Layer
EB[BP_EventModule Message Bus]
DB[TABLE_RegisterEvent] -- Defines --> EB
BPC_L -- Broadcasts --> EB
BPC_P -- Broadcasts --> EB
end

subgraph UI Framework
UHP[UMG_HudPannel Controller]
EB -- Triggers Update --> UHP
UHP --> LC[UMG_HudLapCounter]
UHP --> RK[UMG_HudRanking]
UHP --> PK[UMG_HudPickup]
UHP --> TM[UMG_HudTimer]
end

Core Implementation Skills

Adaptive HUD Framework (UMG_HudPannel)

The primary UI container, UMG_HudPannel, was designed to handle high-cardinality data and dynamic screen real estate.

  • Multi-View Logic: Using an enumeration-based system (E_Layout), I implemented func_RearrangeLayout to automatically shift UI anchors and widget instances between Single Player, Horizontal Split, and Four-Way Split modes.
  • Dependency Injection via BPC_KartHud: I utilized BPC_KartHud as a bridge component, injecting valid gameplay references into the HUD during the initialization phase to avoid runtime GetActorOfClass calls.
0:00
/0:00
Multi-layout HUD supporting dynamic split-screen rearrangement based on player count.
Split screen layout variations by player count
Split-screen layout configurations adapting to 1, 2, and 4 player modes.

Componentized Lifecycle Management

Each HUD element was built as a standalone, event-receiving unit. This modularity allows for rapid iteration on individual features (Ranking, Timer, Lap Counters) without risking the stability of the entire HUD stack.

  • Ranking & Progress: The ranking system utilizes the global bus to update player hierarchy in real-time based on distance-to-spline metrics.
Ranking widget component
Ranking Widget. Real-time placement tracking within the competitive HUD.
  • Adaptive Timing: The timer and lap counter components utilize cached event data to update only when a valid state change (e.g., crossing a sector gate) is detected, minimizing UI tick overhead.
Lap counter widget with adaptive layout
Lap Counter. Adaptive widget reacting to progression events with layout-aware positioning.
Time counter widget with adaptive layout
Time Counter. Performance-optimized timer component with adaptive positioning per split mode.
  • Pickup Display: The pickup widget listens for item acquisition events and displays the current power-up state, fully decoupled from the pickup gameplay logic.
Pickup widget with adaptive layout
Pickup System Widget. Event-driven item tracking unit with layout-responsive positioning.

Data-Driven Global Event Bus

The foundational layer is the BP_EventModule, which standardizes communication across the entire project.

  • Low-Code Registration: By using TABLE_RegisterEvent, I allowed designers to add new game events (e.g., “Nitro Used”, “Target Locked”) via a simple DataTable row.
  • Event Holder Pattern: Each event is backed by a DA_EventHolder data asset, ensuring that event signatures remain consistent even when used across diverse systems like VFX, SFX, and UI.

Design Philosophy

Across the HUD framework and event bus, several principles guided the architecture:

Reactive Over Polling — The entire UI layer operates on a push model. No widget polls for state on tick. Every update is triggered by an event broadcast through the global bus, keeping per-frame overhead near zero regardless of widget count.

Layout as Data — Split-screen configurations are not separate widget trees. A single UMG_HudPannel instance reads an E_Layout enum and repositions anchors, sizes, and visibility programmatically. Adding a new layout mode means adding an enum value and its anchor data, not duplicating widgets.

Component Isolation — Each HUD element (Ranking, Timer, Lap Counter, Pickup) owns its own initialization, teardown, and event subscriptions. One component crashing or being removed has zero impact on the rest of the HUD stack. This made parallel development across team members frictionless.

Designer-Friendly Extensibility — The TABLE_RegisterEvent DataTable lets designers define new game events without touching Blueprint graphs or code. Combined with the DA_EventHolder data asset pattern, event signatures stay type-safe while remaining accessible to non-programmers.

Minimal Coupling — Gameplay systems never hold references to UI widgets. BPC_KartHud acts as the sole injection point during initialization, and all runtime communication flows through the event bus. This means any gameplay system can be tested independently of the UI, and vice versa.