I am not sure this is exactly what @ClockworkOcean is suggesting, but possibly.
You create a C++ Class, say MyHealthBar that derives from UUserWidget. From that, you create a widget that has it as itâs class, it might be called UMG_MyHealthBar.
In your actor class, you start that MyHealthBar/UMG_MyHealthBar class with CreateWidget and Add to Viewport. This gives you a pointer to that class which you save in private space of the actor/controller.
Then MyHeathBar/UMG_MyHeathBar can access any variables the Actor Class can poke in via the pointer to the MyHealthBar class that was returned when you created the widget. In that MyHeathBar, for example, you might have a UPROPERTY that is a float CurrentHealth. The actor can update that, and the widget either has a Bind to grab the value or a function to do something more complex with it.
This also allows two way communication so the widget can have functions the Actor Class might execute, like an implementable event. The MyHealthBar class can also have UFUNCTIONs that can be implemented within the MyHealthBar Class, say SetHealth(float NewHealth). These can be called from the Actor Class. You can even put some C++ code in the MyHealthBar widget to be a go between for tricky things you would like the UMG widget to do.
No casting should be necessary if you start it with the subclass and save the pointer in an appropriate variable (appropriate being not UUserWidget but the derived UMyHeathBar C++ class).
In the actor class (actually the player controller or at least by referencing the playercontroller, I do all of this in the playercontroller or AIController if I have a HUD on them for player to see) you might reference it by:
.h
UPROPERTY(EditAnywhere,BlueprintReadWrite,Category=âHeath HUDâ)
TSubclassOf wHealthBar;
UPROPERTY(BlueprintReadWrite,Category=âHealth HUDâ)
UMyHealthBar* RuntimeHealthBar;
.cpp (say in beginplay)
if(wHealthBar) { RuntimeHealthBar=CreateWidget(this,wHealthBar); }
if(RuntimeHealthBar) { RuntimeHealthBar->AddToViewport(); }
Now you have a pointer to your derived HealthBar.
In the C++ widget class (the UMyHealthBar)youâve createdâŚ
.h
âŚ
class _API UMyHealthBar : public UUserWidget
âŚ
public:
UPROPERTY(BlueprintReadWrite,Category=âHealth Barâ)
float MyHealthAmount=0.f;
.cpp
nothing if you donât have something you want to do with it.
At this point, you will have reparented your UMG widget to the UMyHealthBar class and in the Actors playercontrollers property view, youâll have set the wHealthBar to your UMG Widget.
Now the actor class can put a value into the UMyHealthbar class like:
RuntimeHealthBar->MyHealthAmount=TheHealthIJustFiguredOutInTakeDamage;
The widget can find this variable value in the bind of say a text widget, or actually do a Get on it and do things with it, like a calculating a percentage or something.
Iâm not sure the above is correct, just typed it from another screen with my code, but itâs the idea.