Gamasutra is part of the Informa Tech Division of Informa PLC

This site is operated by a business or businesses owned by Informa PLC and all copyright resides with them. Informa PLC's registered office is 5 Howick Place, London SW1P 1WG. Registered in England and Wales. Number 8860726.


Gamasutra: The Art & Business of Making Gamesspacer
View All     RSS
April 21, 2021
arrowPress Releases







If you enjoy reading this site, you might also want to check out these UBM Tech sites:


 

UE4Cookery CPP002: Static delegate trick

by Artur Kh on 03/05/21 10:21:00 am

The following blog post, unless otherwise noted, was written by a member of Gamasutra’s community.
The thoughts and opinions expressed are those of the writer and not Gamasutra or its parent company.

 

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...


Related Jobs

Zovolt Ltd
Zovolt Ltd — Lisbon / Dublin, Remote, Remote
[04.20.21]

Unreal Engine Software Developer
Sucker Punch Productions
Sucker Punch Productions — Bellevue, Washington, United States
[04.19.21]

Audio Programmer
Sucker Punch Productions
Sucker Punch Productions — Bellevue, Washington, United States
[04.19.21]

Multiplayer/Network Programmer





Loading Comments

loader image