In this lesson, you will learn how to create a bridge between your PlayerController and your User Interface (UI) widgets to display real-time game data.
The Role of the Controller as a Traffic Controller
In the Unreal Gameplay Framework, the PlayerController acts as the "brain" of the player. While your Character class handles physical movement, the PlayerController manages the high-level logic, such as inventory states, health values, or score tracking. However, the UI is a separate layer. To show a player's current health on the screen, the UI widget cannot simply "guess" the value; it must be told by the PlayerController.
Establishing the Connection
The most robust way to route this information is through a Direct Reference. When your game begins (typically in the BeginPlay event of the PlayerController), you create an instance of your UI widget and store a reference to it in a variable.
Once you hold this reference, your controller can "push" updates to the widget whenever a relevant event occurs.
For example, imagine a function inside your UI widget called UpdateHealthBar(float NewHealth). Your PlayerController would call this whenever the health changes:
// Inside PlayerController.cpp
void AMyPlayerController::OnHealthChanged(float NewHealth)
{
if (MyUIWidgetInstance)
{
MyUIWidgetInstance->UpdateHealthBar(NewHealth);
}
}
Why This Matters
Routing events this way keeps your project organized. By centralizing the logic in the PlayerController, you ensure that the UI stays "dumb"—it doesn't need to know how health is calculated or why it changed; it only knows that when the Controller sends a value, it should update the screen. This separation makes your code easier to debug because all data flow originates from the controller, which serves as the single source of truth for the player's status.
Key Takeaway: Use the PlayerController to hold a reference to your UI widget and push state updates to it, keeping your UI display responsive and your gameplay logic cleanly separated.