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:
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.
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
We now go on from this. On False, we simply add the Widget to the Viewport:
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:
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:
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”:
Open the Enum Object and add “None”, “Normal”, “Rare” and “Boss”.
This Enum will be our Icon Helper… you can Expand it as you like.
Back to the Enemy Blueprint.
We add the following Variables:
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:
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:
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.