informa
3 min read
article

UE4Cookery CPP002: Static delegate trick

Topic: Static delegate trick Source for UE4.23: https://github.com/klauth86/UE4Cookery/tree/main/CPP002

Sometimes we need to implement interaction between classes from different layers. For example, let's take a look at Player class and it's interaction with some UI Widget. Let it be UI Widget for Game Menu with floating Show/Hide mechanic. The main thing - how can we pass some signal from Player to UI Widget. One approach - to include all stuff, use UGameplayStatics to get Player instance and so on. However, this approach make it a little bit too coupled. One trick, that can be used here - static delegate. Let's make it through step by step.

First of all, lets create namespace, that will hold all UI Delegates. Also we add forward declaration for Player class. So that will be

 

UIDelegates.h

#pragma once

#include "Delegates/DelegateCombinations.h"

class AMyDefaultPawn;

namespace UIDelegates {

	DECLARE_MULTICAST_DELEGATE_OneParam(FToggleMenuEvent, AMyDefaultPawn*);

	extern FToggleMenuEvent OnToggleMenu;
};

 

and don't forget to add definition for extern thing in CPP

 

UIDelegates.cpp

#include "UIDelegates.h"

UIDelegates::FToggleMenuEvent UIDelegates::OnToggleMenu;

 

Ok, now we need to see Player class that will use it

 

MyDefaultPawn.h

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "GameFramework/DefaultPawn.h"
#include "MyDefaultPawn.generated.h"

UCLASS()
class CPP002_API AMyDefaultPawn : public ADefaultPawn {

	GENERATED_BODY()

protected:

	virtual void SetupPlayerInputComponent(UInputComponent* InInputComponent) override;

	void ToggleMenu();
};

 

MyDefaultPawn.cpp

// Fill out your copyright notice in the Description page of Project Settings.

#include "MyDefaultPawn.h"
#include "Components/InputComponent.h"
#include "UIDelegates.h"

void AMyDefaultPawn::SetupPlayerInputComponent(UInputComponent* InInputComponent) {
	Super::SetupPlayerInputComponent(InInputComponent);

	InInputComponent->BindAction("ToggleMenu", IE_Pressed, this, &AMyDefaultPawn::ToggleMenu);
}

void AMyDefaultPawn::ToggleMenu() { UIDelegates::OnToggleMenu.Broadcast(this); }

 

And what about UI Widget? It can be very simple, just like this

 

GameMenuWidget.h

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "Blueprint/UserWidget.h"
#include "GameMenuWidget.generated.h"

class AMyDefaultPawn;

UCLASS()
class CPP002_API UGameMenuWidget : public UUserWidget {

	GENERATED_BODY()

public:

	UFUNCTION(BlueprintImplementableEvent, category = "Game Menu Widget")
	void OnToggleMenu(AMyDefaultPawn* pawn);

protected:

	virtual void NativeConstruct();

	virtual void NativeDestruct();
};

 

GameMenuWidget.cpp

// Fill out your copyright notice in the Description page of Project Settings.


#include "GameMenuWidget.h"
#include "UIDelegates.h"

void UGameMenuWidget::NativeConstruct() {
	Super::NativeConstruct();
	UIDelegates::OnToggleMenu.AddUObject(this, &UGameMenuWidget::OnToggleMenu);
}

void UGameMenuWidget::NativeDestruct() {
	UIDelegates::OnToggleMenu.RemoveAll(this);
	Super::NativeDestruct();
}

 

Note, that all subscriptions are operated in NativeConstruct and NativeDestruct methods. The first one is called just before Widget is added to Display hierarchy and the second - when it is removed from hierarchy. As for BlueprintImplementableEvent - they are used to implement some logic in BPs for things that have hard dependencies with visual elements.

 

So, let's do the last things - create BP around our UI Widget and put some visual logic to it:

 

BP_GameMenuWidget_Designer

BP in Designer

 

BP_GameMenuWidget_Graph

BP Graph

 

And that's it! And here is raw result

Result

 

So, static delegates can be really helpful in the sense of accessing objects (when it is a problem to access them directly) and resolving class dependencies and coupling...

Latest Jobs

Treyarch

Playa Vista, California
6.20.22
Audio Engineer

Digital Extremes

London, Ontario, Canada
6.20.22
Communications Director

High Moon Studios

Carlsbad, California
6.20.22
Senior Producer

Build a Rocket Boy Games

Edinburgh, Scotland
6.20.22
Lead UI Programmer
More Jobs   

CONNECT WITH US

Register for a
Subscribe to
Follow us

Game Developer Account

Game Developer Newsletter

@gamedevdotcom

Register for a

Game Developer Account

Gain full access to resources (events, white paper, webinars, reports, etc)
Single sign-on to all Informa products

Register
Subscribe to

Game Developer Newsletter

Get daily Game Developer top stories every morning straight into your inbox

Subscribe
Follow us

@gamedevdotcom

Follow us @gamedevdotcom to stay up-to-date with the latest news & insider information about events & more