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