Help creating multiple health bars

I tried to create a health bar that works when there are multiple enemies on screen. I’ve a widget called “enemyHealthBar”, and what I must do is change the variable HP (which is inside the widget) from my enemy blueprint. I tried 2 ways (this screenshot is from the enemy blueprint):

The first, the cast to enemyHealthBar, fails. The second, create enemy health bar widget, doesn’t actually change the variable value.
Link to the post that I followed:

The first failed, cause the Variable “Widget” is Null… Means… Nothing inside it…

You need to SET this variable right after Create Widget, before add to viewport.
Be sure, that this Variable has the Type of your Widget… Which seems, as i can see from the Screenshot, to be “Enemy Health Bar”.
I would recommend to get rid of Spaces in Filenames and Paths… Just cause they can bring trouble.
To set the variable:
Drag the variable into the Graph while holding the ALT Keybind… Or select “Set” when asked for get or set.
Than drag a line from the blue output on the right of create weight, into the set node of the Variable.
Alternatively… When you don’t want to create a variable first… You can rightclick that blue output of create Widget, and on Top you see “Promote to variable”. this automatically creates a new variable of the selected Class Type for you… And directly creates a Set node with Link to Create Widget.

And then… After setting that Variable, you have no need to cast for it, since it already has the correct type.

As a second:
You don’t need a Sequence for that job.
Replace your Sequence with a Validate Check Node for the Widget Variable.
To do so:
Get the Variable by dragging it into the graph while holding CTRL… Or choose “get” when asked for get or set.
Rightclick that Get Node and at the very bottom you’ll find the “Convert to validate Check”

On NotValid, you create the widget, set the variable, add to viewport AND after that, simply get/set the HP Values. You dont need to cast for anything.
On Valid, you just skip all the create part and directly link to the set/get of the HP…

So… Now my Recommendation for you:
Don’t create a new Widget for a Health Bar, for every enemy you overlap/hit/else…

What you want to do is:
Create the Widget and the Widget Variable inside the GameState!
Simply create a GameState Class and set it as default GameState in your GameMode (you need to look for a small tut… Cause i’m on mobile night now).

Inside the GameState, create a new Function (not Event!) And call it “UpdateEnemyHealth”
As Input Parameter for the Function set:
Name of type Text
Health of Type Vector2D

And just copy your code in this function.

Now the Tricky part.

In your Actor Cursor begin Over, you add a Node called “get GameState”.
This GameState, you need to cast to your custom one. Now rightclick the cast and “convert to pure cast”, since a GameState is always existing before any actor… We don’t need an execution input.
Now your cast is a little bit smaller and only has two outputs… Ignore the red bool for now and simply drag from the blue GameState of your Type… And call the Update Enemy Health Function there…
You will need to add a Text (i recommend that!) For the enemy Name.
And the Vector2D Input:
You rightclick it and “Split” use the X value as Current Health and the Y Value as MaxHealth.

In the function, same thing… You can split the Vec2 Input to get your two floats from to calculate the health Bar stuff.

In your widget, you’ll need to add a Text Object to your HealthBar, to show the Enemy Name above it.

This way, you really show only 1 Health Bar for all enemies, that updates its content to whatever enemy your mosque hovers.

1 Like

Once the mouse hovers the enemy, I did: create widget, click the blue dot from create widget and promote to variable of type “enemyHealthBar”. Then drag the blue dot to “set HP” then add to viewport.


Doesn’t work, the hp remains unchanged, stills is the default value.
I also did the below, but doesn’t work either:

You are creating a widget every time you hover the actor with the Mouse! Don’t do that! You are creating a Widget over Widget over Widget… And so on…

So your widgets overlay each other.
As told:
Create ONE Widget in the GameState and not in the actual Actor.

It’s not in the screenshot, but I remove the widget once the mouse stopped hovering the enemy though. But why is the variable “HP” not being setted correctly? Is because I’m creating the widget on mouse hover? The variable HP never changes from the default value, how do I change its value from inside the enemy blueprint, this is all I need.

Creating and Removing a Widget over and over again is still not a good way to Handle UI Elements ^^"

But… i was on my PC the last half hour and tinkered you the following piece…:

MY “TEN STEPS TO SUCCESS” TUTORIAL…
for a on Map Healthbar

Create a new Blueprint Class:


As Type, select the GameState Class:

And call it “GS_Main”.

Repeat 1, but Set GameMode as Class. Call it GM_Main.

Open your GM_Main and set your GS_Main as GameState Default.

Go into your Project Preferences and set your GM_Mode as Default gameMode under Maps & Modes:

Now you are Prepared to do some Widgets…
This is my UI_MapHealthBar Widget.


The marked Widgets are set as isVariable, so i can manipulate them in the Graph.

In the Graph, i created a new FUNCTION. I called it “UpdateHealthBar”
In the Screenshot, you see the Input Pins and their Types:
06

We now populate our healthBar. Here a short but very very useful Workflow for Functions… you don´t need to drag a Line from the Input, all over to the target Node… You can GET every Input pin by simply rightclick the Graph and type in "Get ".
So this, is the whole Graph:

You now head to the GS_Main. Here, add a new Function, too.
This new Function has the Same Name, Inputs and Input Types as the Function in the Widget.
See:

We now create the UI_MapHealthBar Widget FIRST.
09
And from the marked output, rightclick it, and “Promote to Variable”


This creates us the correct Type Variable, automatically.

We now use the Trick for a Validation Check again, and Split the Function Graph into two Branches:


This makes sure, we have this Widget created one time only! Since we want to safe some memory and don´t want to feed the Garbage Collection with one and the same Widget over and over again, we recycle the Usage!

So… From the Is Not Valid, we simply connect the Creation of the Widget. After that, we ask if the Widget is in Viewport, or not.


This makes sure, we don´t add the same Widget to the Viewport multiple Times.
Edit: Connection the Set of the Widget Variable with the Branch, too. That is missing in the Screeny … Sry :pray:t2:

We now go on from this. On False, we simply add the Widget to the Viewport:
13

Now we casll the UpdateHealthBar from the Widget, from both Branch Executions… the True and the False. As Input, we get the Function Input parameters and Link them 1:1…:

Thats all for this Blueprint.

We now Head over to your Enemy Actor.
Make sure that, either in your Capsule Component, or in your Mesh Mesh Component, the “Generate Overlap Event” is set to true in the Detail Tab.
We Start with your “Event ActorBeginCursorOver”.
First, Get the GameState:
15
You´ll notice, that this GameState is of the Base Class you selected in the Blueprint Selection in 1).
Sow… we need to Cast this to our Custom one:
16
Since we named the GameState “GS_Main”, we simply search for the Cast to “GS” and it will list our Custom Class in the Context Browser.

From this Cast, you may know it… we call the UpdateHealthBar Function:

Now… we come to the final Part of this “Ten Steps to Success” Tutorial…
We need some variables for the Enemy.
We first want to create an Enum.
So… head to the Content Browser, rightlick > Blueprint > Enum. Create it and Name it “Enum_EnemyType”:
18
Open the Enum Object and add “None”, “Normal”, “Rare” and “Boss”.
19
This Enum will be our Icon Helper… you can Expand it as you like.

Back to the Enemy Blueprint.
We add the following Variables:
20
I set all the Variables to Editable and Expose On Spawn.
Later, you may want to have a DataTable for the Base Enemy Stats… we now go with this…
Get all variables into the Graph and link the Health and Name to the Updater:
21
Since you want to Show the HealthBar Widget, we keep Widget Visibility to Visible, same goes for Name, cause it makes it easier to identify the Enemy.
Now the more tricky Part… the Icon…

from the Enum variable, take two Selects and link them as follows:


We now set the Visibility for the Icon to “Collapsed” on the “None” Input.
And, you can set different Icons for different Enemy Types. You can leave the “None” Icon empty, cause it never gets Set if the validation Check in the Widget fails.
So:

Excuse my Icon names… i was to lazy to draw some new for this… or rename existing ones… sry ^^"

We now create a new Event… you know it… the “Event ActorEndCursorOver”.
Here, we make a GetGameState and Cast again.
After the Cast, we just call the UpdateHealthBar again… and just set the WidgetVisibility to Collapsed:

This is everything, we will setup here right now… Yes… no more Mesh or anything…
There is a reason for this…
All you´ve done here now, is prepare a Base Class for ALL your Enemies…

What you do now is:
Head over to the Content Browser again and Rightclick your Enemy Actor.
On the Top of the Context List, you´ll find “Create Child Blueprint Class”.
This Point is your best Friend for Future Enemies for now. Click it!

You now created a Child Actor of your Enemy Actor Class. This Child Actor contains EVERY Component, Variable, Function…etc from the Base Enemy Actor, but allows to manipulate them individually.
So… set up your Name, Health and Type Variables in the Child enemy and drag em into the Scene.

Test it… voilà… that´s it…

Aditional Content:
You my recognizte, that your Healthbar is now fixed to the Top Left of the Screen, strecthing over the full Width.
How to fix that?
You can go into the Widget and select the VerticalBox (which is the first Widget in the UI_MapHealthBar). rightclick it and select
Wrap with > SizeBox
THis will wrap your whole Widget into a new Box, where you can set its MaxWidth and height Override.
you now can setup its position on the screen, by going into your Graph again, into the function to Update and add a “SetPositionInViewport” for the Self Object:
26
The Position you Set here is absolut on the 2D Screen. you either can calculate it or… for Example, add a new input to the function, that you can set the Position to via the Functions in the GameState and the Call in the Base Enemy Actor.
F.e.: you can get the Actor World Position, change Matrix with “ProjectWorldToScreen” and Place the Widget on the Screen Position, resulting from that…

Known problem:
It happens that the HealthBar flickers… that happens when two actors overlap directly… and the ActorBeginCursorOver and EndCursorOver are struggling which one is the nearest…
I fixed it here by setting generate Overlap Event on the Mesh, instead of the Capsule… but perhaps someone has a better solution here…

Sidenote:
You can Make the HealthBar visible and hide it from any other Actor or Widget, by simply getting the GameState, cast it to your Custom… and call the Updater Function…

Resulting Screen here:

To Change the Health of an Enemy:


In the Base Enemy Actor.
If you directly want to update the Healthbar… even if not hovered with the Mouse… simply call the Update Function in the GameState again.

Edit:
I used the GameState Class here as Hub for the Widget. You can use a PlayerController or any other Level Default Actor as HUB, too.

2 Likes

:1st_place_medal: for the longest post. Neat. This should be a tut in your profile because I beg to differ that:

image


Here’s another thing that may push you in the right direction: