Setting Up a Widget with C++ Inside Unreal Engine 5

Set up a basic widget with text and a progress bar in C++ using BindWidget to connect the variables

Unreal Engine 5 health user widget above Quinn's head in default map
Quinn with a health bar

Software Versions: Unreal Engine 5.5.0 | Rider 2024.3

Project Name: MyProject

In this example we'll make a very basic UserWidget that will be initialized using C++. Something new I learned was that using meta = (BindWidget) is the main key to helping us connect C++ to BP widgets.

Before beginning ensure your build.cs file has UMG added to the dependcies and uncomment the Slate UI private dependency modules.

MyProject.Build.cs

using UnrealBuildTool;

public class MyProject : ModuleRules
{
	public MyProject(ReadOnlyTargetRules Target) : base(Target)
	{
		PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;
	
		PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "EnhancedInput", "UMG" });

		PrivateDependencyModuleNames.AddRange(new string[] {  });

		PrivateDependencyModuleNames.AddRange(new string[] { "Slate", "SlateCore" });
	}
}

Start by creating a new Unreal class from UserWidget

Unreal Engine 5 new C++ user widget class
New UserWidget C++ class

Name it whatever you want, I name it MyWidget_Health. In the header file I declared a UCanvasPanel, UTextBlock, and UProgressBar for basic construction of the widget. In the UPROPERTY macro it's critical to use meta = (BindWidget) if you want to use these variables in Blueprints. Furthermore, using BindWidget the names we use to name our variables must match the names in the BP widget to compile successfully. I also added a couple of functions to set the text and progress bar percentage that I'll use later on in another section.

MyWidget_Health.h

#pragma once

#include "CoreMinimal.h"
#include "Blueprint/UserWidget.h"
#include "MyWidget_Health.generated.h"

class UCanvasPanel;
class UProgressBar;
class UTextBlock;

UCLASS()
class MYPROJECT_API UMyWidget_Health : public UUserWidget
{
	GENERATED_BODY()

public:
	UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (BindWidget))
	UCanvasPanel* Panel;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (BindWidget))
	UTextBlock* Name;
	
	UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (BindWidget))
	UProgressBar* HealthBar;

	UFUNCTION(BlueprintCallable)
	void SetHealth(float NewHealth);

	UFUNCTION(BlueprintCallable)
	void SetName(FString NewName);
};

Below is the .cpp file that has basic setter functions that can be used by actors inheriting this widget. An example of actor using it can be seen here on the MyStructPlayer actor.

MyWidget_Health.h

#include "MyWidget_Health.h"
#include "Components/ProgressBar.h"
#include "Components/TextBlock.h"

void UMyWidget_Health::SetHealth(float NewHealth)
{
	float NewHealthPct = NewHealth / 100.f;

	HealthBar->SetPercent(NewHealthPct);
}

void UMyWidget_Health::SetName(FString NewName)
{
	FText NewNameText = FText::FromString(NewName);
	
	Name->SetText(NewNameText);
}

Next, after compiling, create a Blueprint UserWidget with our new MyWidget_Health class as the parent. In order for this to compile we need to add all the properties we added in the in header file and name them the same. Using meta = (BindWidget) is looking to match the variables in the header file with the Blueprint.

Unreal Engine 5 user widget basic health component  with name and red progress bar
Health widget variable naming

I added a Canvas Panel, Text Block, and Progress Bar to widget tree. In the top left I renamed them according to the header file, so I renamed the Canvas Panel to Panel, Text to Name, and the Progress Bar to HealthBar. The widget should now compile successfully and we can use it in our project.

Although this is a rudimentary example it's fun to see the potential this unlocks.

Loading...