It's tough to know where to start when setting up the UI for your game. There are a lot of existing Unreal classes that are suitable for housing your UI-related code. I'll describe what has worked for me so far.

  1. First, we will create some base C++ classes from which our Blueprints will derive.
  2. Then we will create the Blueprint subclasses, and make Unreal use them.
  3. We will add example functions to create a widget on calling ShowMenu(), and hide on calling HideMenu().

Create C++ Subclasses

A lot of Unreal setup boils down to subclassing existing classes to specify custom behaviour. In this case we will need to subclass AGameModeBase and AHUD in order to set up our custom UI manager.

Create C++ Subclass of AGameModeBase

If you haven't done it already, create a C++ or Blueprint subclass of AGameModeBase. We will need to use this to specify which HUD class is used in our levels. It's useful in general for choosing custom subclasses of APlayerController, AGameState and other core classes.

I recommend creating a C++ base class, and then a Blueprint subclass of that. I prefer to write logic in the C++ class so debugging and breakpoints are all available from C++ and then use Blueprint-exposed properties to connect things together and set gameplay variable values.

For this example we will be using the naming conventions described in UI Best Practices.

The easiest way to create a new C++ subclass is under File > New C++ Class

Class diagram for our game mode class and Blueprint

The default generated C++ is fine for what we need. We will be specifying our custom AHUD subclass in the blueprint.

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/GameModeBase.h"
#include "BUIGameModeBase.generated.h"

UCLASS()
class EXAMPLE_API ABUIGameModeBase : public AGameModeBase
{
	GENERATED_BODY()
	
};

As a side-note there is also a built-in Unreal class named AGameMode, but I would recommend using AGameModeBase. AGameMode is somewhat of a relic Unreal Engine's past as an engine that focused on match-based shooters, and comes with a lot of built-in functionality that is not always useful.

Create C++ Subclass of AHUD

In the same way we created a subclass of AGameModeBase, now we will create a C++ subclass of AHUD. AHUD is a class that is created by and owned by APlayerController. For our purposes it will do fine.

Class diagram for our custom subclasses of AHUD.

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/HUD.h"
#include "BUIHUD.generated.h"

UCLASS()
class EXAMPLE_API ABUIHUD : public AHUD
{
	GENERATED_BODY()
	
};

The default BUIHUD.h and BUIHUD.cpp are OK, we will be adding functionality to it after we have hooked them up in Unreal.

Create Blueprint subclasses

Now that we have created C++ classes ABUIGameModeBase and ABUIHUD, we can re-start Unreal and create our Blueprint subclasses.

Right-click in the Content Browser, and choose Blueprint Class from the pop-up menu. See the diagram below

  • We will now need to set the C++ parent class for this Blueprint. Choose BUIGameModeBase and name your blueprint BP_GameMode.
  • Do the same for BUIHUD, creating a Blueprint called BP_HUD.

Creating Blueprint subclass of ABUIGameModeBase

With both Blueprints created, we can now set BP_GameMode to use BP_HUD as its HUD class.

World Settings

In order for our custom BP_GameMode Blueprint to be used, we must set it in the World Settings for our level. This window can be opened with:

Window > World Settings.

Then choose BP_GameMode from the GameMode Override dropdown.

Set the custom BP_GameMode in World Settings

Using HUD Subclass to Create Example Main Menu

Phew, that was a lot of set-up, but thankfully we only have to do it once. Adding functionality from now on will be much easier.

We can now use our ABUIHUD class as the manager for our UI.

Let's add an example function that creates a MainMenu widget when a function is called.

BUIHUD.h

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/HUD.h"
#include "BUIHUD.generated.h"

UCLASS( Abstract )
class EXAMPLE_API ABUIHUD : public AHUD
{
	GENERATED_BODY()

	// Make BlueprintCallable for testing
	UFUNCTION( BlueprintCallable )
		void ShowMainMenu();
	UFUNCTION( BlueprintCallable )
		void HideMainMenu();
	
protected:
	UPROPERTY( EditDefaultsOnly )
		TSubclassOf<class UUserWidget> MainMenuClass;

	// Keep a pointer to be able to hide it
	UPROPERTY()
		class UUserWidget* MainMenu;
};

BUIHUD.cpp

#include "BUIHUD.h"
#include <GameFramework/PlayerController.h>
#include <Blueprint/UserWidget.h>
#include <Kismet/GameplayStatics.h>

void ABUIHUD::ShowMainMenu()
{
	// Make widget owned by our PlayerController
	APlayerController* PC = Cast<APlayerController>( GetOwner() );
	MainMenu = CreateWidget<UUserWidget>( PC, MainMenuClass );

	MainMenu->AddToViewport();
}

void ABUIHUD::HideMainMenu()
{
	if ( MainMenu )
	{
		MainMenu->RemoveFromViewport();
		MainMenu = nullptr;
	}
}

If we create a test main menu UUserWidget Blueprint, and set the MainMenuClass property in BP_HUD, we can spawn it when the ShowMainMenu() function is called.

Showing Main Menu from C++

From C++ showing the main menu would look like this:

APlayerController* PC = UGameplayStatics::GetPlayerController( GetWorld() );
ABUIHUD* HUD = PC->GetHUD<ABUIHUD>();
HUD->ShowMainMenu();

Showing Main Menu from Blueprints

From Blueprints showing the main menu would look like this:

Simple test Blueprint to show and hide the main menu

Final Result

Look, we have a menu, managed in a AHUD subclass, and created via C++!

Posted: