How did I deal with…?
Using Delegates to Establish Communication between User Interface and Gameplay
The goal of this project is to make a video game, reusing a single C++ template in each level for the most relevant actors. Using Blueprints to solve level‑specific situations enables the single C++ programming, to keep working on all levels. That's also true for future low level programming changes. This is what the basic programming looks like in the prototype:
The User Interface (UI) reacts to the overlapping on the pickup, telling you to click on “E” key, in order to:
- Pick up the element
- While collecting the item
- Updating the pickup counter, and
- Sending hints about what to do next.
When all items are collected, the UI tells you that the exit gates are unlocked and you can go through them to the next level:
These are the steps of the Delegates' implementation:
C++ logic schematics
The UI is constantly telling you what you are interacting with. Instead of casting every time to new actors – which may end up putting a strain on the CPU – my solution consists of:
- Using events to broadcast Delegates, and
- Changing text in UI.
First I'm making a prototype using Blueprints and Event Dispatchers (That's what Delegates are called in Blueprints). Once this prototype is functional, I'm in the position to draw a schematic for Interaction:
Delegates declaration
With this schematic in mind and my functional Blueprint prototype, I can start translating to C++. This is what my Delegates declarations look like in the header of my Player Character (most of the UI updates come from the Interaction function):
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FMission);
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FCounter);
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FHint);
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FMessage);
And this is what their definitions look like:
public:
ASciFiProjCharacter();
//************ Delegates
UPROPERTY(BlueprintAssignable)
FMission StartMission;
UPROPERTY(BlueprintAssignable)
FMission Mission_Accomplished;
UPROPERTY(BlueprintAssignable)
FHint Interact_Empty;
UPROPERTY(BlueprintAssignable)
FHint Interact_OneToGo;
UPROPERTY(BlueprintAssignable)
FHint Interact_Finished;
UPROPERTY(BlueprintAssignable)
FCounter Add_Item;
UPROPERTY(BlueprintAssignable)
FMessage Overlapping_Pickup;
UPROPERTY(BlueprintAssignable)
FMessage All_Pickups_Collected;
Broadcasting
I just have to broadcast them in the source file whenever an event happens to send a message to the UI, for instance, when you're overlapping a pickable object inside the OnOverlapBegin function:
Overlapping_Pickup.Broadcast();
Listeners in Blueprints
Here is the Listener in the UI Blueprint's Event Graph:
Updating UI
Updating Messages Panel:
I'm solving the text‑replacing operation with a macro (Showing Message) and reusing it every time an event takes place:
Event Dispatchers
This method allows to automate the visibility of the messages and let designers update the texts manually in Blueprints, instead of trying to hard code the messages in C++.
Almost every element in this level has its own delegates. I am using a couple of Event Dispatchers for the sake of efficiency, meaning, solving in C++ only what is repeating in every possible level and leaving local changes to Blueprints.
Here is an example:
This Event Dispatcher sends a message to UI every time the player character collides with the drain system, which exists only in this level:
This is the listener in Hints Panel UI Event Graph:
And this is the Custom Event updating text:
There is a lot more about programming UI and Interaction in Real Time. Delegates are just one tool in a big set which happen to work right for this specific project. Take a closer look at other tool‑sets by visiting these case studies: