How did I deal with…?

Programming Video Game Interaction Using a C++ Interface in Unreal Engine

The goal of this workflow development is to provide the player with an efficient interaction, using as few resources as possible on picking up collectibles inside the level. Here you can see the block out of your player character in front of a changing color collectible, from yellow to orange, indicating that it's ready to pickup.

Getting close to pickup Getting close to pickup Getting close to pickup
The proximity to the pickup makes it change color and updates the UI.

These are the steps I'm taking to plan, test and implement my interaction:

Picking up item

I'm basing the interaction on events instead of casting functions to actors. To achieve that, I'm using an Interface (don't confuse with User Interface) and triggering delegates (Event Dispatchers in Blueprints).

Collecting item Collecting item Collecting item
Delegates act as events, changing text in the UI and color on the pickup.

One Page Design Document: Single Level

First of all, I am defining the interaction patterns in the game, using the project's gameplay as a template. This is how I am summarizing the general logic, using schematics from the One Page Design Document:

Single Level from One page design Single Level from One page design
Same logic repeats through all levels.

User Interface Prototype

All levels are going to share the same logic. Only the contents are going to be different, because each level represents a new city. I am drawing a prototype for the User Interface and a Storyboard, to define interactable regions and make the Gameplay's goals visible.

Schematics for interaction pre-production Schematics for interaction pre-production
Schematics for interaction pre‑production, including basic UI layout.

Storyboard

Carousel showing interaction. Click on the arrows to progress through the vignettes.

The storyboard is telling me which functions I am going to need for the interaction:

  1. Opening/closing doors
  2. Input actions system
  3. A set of pickup elements, and
  4. A counter to lock/unlock the exit gates and finish the mission.

C++ Logic Schematics

Now I am in the position to draw a schematics for the general logic of my future C++ version:

C++ Logic schematics C++ Logic schematics C++ Logic schematics
This schematic shows the logic behind the functionalities I'm developing in Blueprints before translating to C++.

First, I am developing a prototype in Unreal Engine/Blueprints, to test the nodes:

All Blueprints interaction methods All Blueprints interaction methods All Blueprints interaction methods
Testing all functionalities in Blueprints before translating to C++.

In this BP sequence you can see the 4 functions I am triggering by pressing the “E” key interaction, namely:

Counter

Inside the prototype, I'm writing a counter that adds items every time I collect a pickup:

Pickups counter Blueprint Pickups counter Blueprint Pickups counter Blueprint
The pickups counter updates the number of collected items.

What I'm doing here is using the same interaction to update my UI via Interface. This is the translation for this first function in C++, in the source file of Player Character, Interact Function:

    
if (Interface && (MissionAccomplished == false))
{
	Interface->Execute_OnInteract(OverlappedActor, this);
	CollectedItems++;
	Add_Item.Broadcast();
}
    

At the end of the conditional, I'm replacing the interface through a delegate, which allows me to send different messages to the UI from C++, reserving the interface for interaction with the pickups only.

Checking out for Active Interface in Pickup

The second function loads up the pickups in the level to check out whether they are implementing the interface or not, leaving the ones with no active interface out of the loop:

Blueprint checking out Interface implementation Blueprint checking out Interface implementation Blueprint checking out Interface implementation
This function checks out whether the pickup has an implemented interface, eliminating all actors from the loop that don't have one.

This is the translation in the public section from header file of parent actor for pickup:

    
UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "Interaction")
	void OnInteract(AActor* Caller);
	virtual void OnInteract_Implementation(AActor* Caller);
        

Checking out One Item Left

The third function tells the UI that the player has only one item left (when the variable int Items equals the variable int TotalItems – 1) and sends a message via Event Dispatcher (future delegate):

Blueprint reaching penultimate pickup Blueprint reaching penultimate pickup Blueprint reaching penultimate pickup
The counter triggers this Event Dispatcher when it reaches TotalItems –1, updating the UI.

This is the Source file in Player Character, Interact function:

    
if (CollectedItems == (TotalItems - 1))
	{
		Interact_OneToGo.Broadcast();
	}
    

This is the delegate definition in the header, triggering an event that pushes text changes in the UI Hints Panel.:

    
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FHint);

UPROPERTY(BlueprintAssignable)
FHint Interact_OneToGo;
    

Checking out All Pickups Collected

The fourth and last function checks out whether all pickups in the level are collected by comparing the int CollectedItems variable and the int TotalItems variable (counting in Game Mode Actor from a Begin Play Event).

Collecting last item Collecting last item Collecting last item
Several delegates modify the level when you collect all items.
Blueprint reaching all pickups collected Blueprint reaching all pickups collected Blueprint reaching all pickups collected
When the counter reaches the total number of pickups, it sends several messages to update the UI, for example, unlocking the gates through the interface.

This last function is executing the following tasks:

  • Stopping the player's ability to collect
  • Labeling the mission as finished
  • Unlocking exit gates, and
  • Updating the UI text via interface.

This is the C++ translation, calling several delegates instead of using the interface. This method proved more efficient than the interface for updating UI after a couple of tests.

    
if (CollectedItems == TotalItems)
{
	CanPickup = false;
	MissionAccomplished = true;
	Mission_Accomplished.Broadcast();
	All_Pickups_Collected.Broadcast();
	Interact_Finished.Broadcast();
}
    

Interact Function

This is what the Interact Function declaration, in Player Character / protected section Header looks like:

    
void Interact(const FInputActionValue& Value);
    

And this is the implementation in source file:

    
void ASciFiProjCharacter::Interact(const FInputActionValue& Value)
{
	if (OverlappedActor && CanPickup)
	{
		IInteractInterface* Interface = Cast(OverlappedActor);

		if (Interface && (MissionAccomplished == false))
		{
			Interface->Execute_OnInteract(OverlappedActor, this);
			CollectedItems++;
			Add_Item.Broadcast();
		}
		if (CollectedItems == (TotalItems - 1))
		{
			Interact_OneToGo.Broadcast();
		}

		if (CollectedItems == TotalItems)
		{
			CanPickup = false;
			MissionAccomplished = true;
			Mission_Accomplished.Broadcast();
			All_Pickups_Collected.Broadcast();
			Interact_Finished.Broadcast();
		}
	}
	else
	{
		if (OverlappedActor == nullptr && CanPickup == false && MissionAccomplished == false)
		{
			Interact_Empty.Broadcast();
		}
		if (OverlappedActor == nullptr && CanPickup == false && MissionAccomplished == true)
		{
			Interact_Finished.Broadcast();
		}
	}
}

The advantage of using Interfaces and Delegates is that I am casting only once to the Interface. Because of that, my character's tick, references, and dependencies are clean and I am executing the interaction only when an Event takes place, rather than on a constant CPU/GPU effort through casting:

  1. The player character approaches the pickup, overlaps
  2. Pickup changes color and character can pickup
  3. UI sends a message
  4. You press “E”
  5. Counter updates, and
  6. UI writes messages/hints.

If we collect enough pickups, the TotalItems number is going to be equal to the number of CollectedItems:

  1. The event unlocks the exit gates
  2. UI sends “Mission Accomplished” messages, and
  3. Game Mode preps end screens.

If you want to see more examples of using programming in real and render time, click on the following case studies links:

Implementing Interface for video game with C++
Implementing C++ Interface

The C++ interface becomes active when overlapping items, sends delegates when the player clicks the “E” key, modifying the environment and other actors.

Delegates communicating UI and Gameplay
Delegates for UI & Gameplay

Using delegates sent by the interface to push text updates in the User Interface and trigger behaviors in the environment, like opening doors.

Adding Input Action from C++ into Unreal Engine
Adding Input Action in C++

Using the existing C++ third person character syntax to create an additional input action binding on UProperties, protected functions, and source.

Programming Gameplay with C++ for Unreal Engine
Programming Gameplay C++

Programming interaction for gameplay in C++ for Unreal Engine, using an interface, delegates and 2 bases for pickups and doors.

Programming automation tool with Python for Maya
Programming Python Tool

Programming an automation tool for Maya using Python to sort unnamed meshes into a conventional hierarchy in outliner by renaming and resetting pivots.

Discover Technical Skills