From this post: UIGradient [LIVE] - #147 by UIScript
Someone earlier messaged me on how I made this; it’s actually pretty simple, and that’s using the new UIGradient.
UIGradient is in beta, meaning this won’t work in a live client. Not to mention only supports linear gradients (for now?), but what I’ve done is used rotation + transparency to achieve this effect.
Now, I’ll try my best to explain this, so bare with me.
First, I’ve created a corner piece of the health bar. The circle was originally going to consist of 3 parts, TopLeft, TopRight, and BottomRight, but I decided for my sanity just to use TopLeft and rotate it.
The image is 500x500, and the thickness of the bar is 120 pixels. If we combine the 3 corner parts, it will result in a 1000x1000 image, translating the thickness to 0.12 in scale if a frame is parented inside a 1:1 frame (which we will use for the horizontal bar).
Now my experiment comes in.
By rotating the UIGradient (from 0 to -90) and by using this Transparency pattern (NumberSequence), you can line up to show a perfect half cut in transparency. The points in the middle are separated by 0.001. Since we know UIGradient rotates by the edges of the frame, setting the rotation to, say -80, will result in a weird skewed image.
To fix that, you’ll have to move the keypoints accordingly to the scale of the rotation (0 to -90).
That’s pretty much all there is to it. We then use math to calculate the rotation and the keypoints position for all 3 corners.
This part will be confusing to a lot of people, and I’m not sure if I can explain this clearly, so I’ve went on ahead and uncopylocked an example that you can grab and check out for yourself:
Going off by what I’ve already created, I’ve made a variable called circleMaxHealth (how much max health will the whole circle hold) which will be the base on how much we need to scale the bar.
We will also work from BottomRight → TopRight → TopLeft to update the visual accordingly.
First, we need to get the minimum health value of each corners based on our circleMaxHealth.
local circleMaxHealth = 100
local function UpdateHud()
local circleAlpha = circleMaxHealth / 3 -- Meaning 33.333 health per corner piece
-- Minimum health values of the corner pieces
local topRightAlpha = circleMaxHealth * (1/3) -- 33.333, same value as circleAlpha but here for the sake of consistency and readability
local bottomRightAlpha = circleMaxHealth * (2/3) -- 66.666
end
Great, we can now check the HP and compare it to our alphas.
local circleMaxHealth = 100
local Health, MaxHealth = 200, 200
local HealthBar = script.Parent:WaitForChild("HealthBar")
local function UpdateHud()
local circleAlpha = circleMaxHealth / 3
local topRightAlpha = circleMaxHealth * (1/3)
local bottomRightAlpha = circleMaxHealth * (2/3)
-- Start the checking of health
if Health <= circleMaxHealth then -- If health is below or equal to circleMaxHealth, then we update the curved bars
Health.Bar.Size = UDim2.new(0, 0, 0.12, 0) -- The horizontal bar HAS to be invisible if our health is below circleMaxHealth
if Health >= bottomRightAlpha then -- If health is above bottomRightAlpha (66.666)
-- TopLeft and TopRight HAS to be visible
HealthBar.TopLeft.UIGradient.Transparency = NumberSequence.new(0, 0)
HealthBar.TopRight.UIGradient.Transparency = NumberSequence.new(0, 0)
elseif Health >= topRightAlpha then -- If health is above or equal to topRightAlpha (33.333)
-- TopLeft HAS to be visible and BottomRight HAS to be invisible
HealthBar.TopLeft.UIGradient.Transparency = NumberSequence.new(0, 0)
HealthBar.BottomRight.UIGradient.Transparency = NumberSequence.new(1, 1)
else -- If health is pretty much below topRightAlpha (33.333)
-- TopRight and BottomRight HAS to be invisible
HealthBar.TopLeft.UIGradient.Transparency = NumberSequence.new(0, 0)
HealthBar.BottomRight.UIGradient.Transparency = NumberSequence.new(1, 1)
end
else -- The curved bars HAS to be visible if our health is above circleMaxHealth
HealthBar.TopLeft.UIGradient.Transparency = NumberSequence.new(0, 0)
HealthBar.TopRight.UIGradient.Transparency = NumberSequence.new(0, 0)
HealthBar.BottomRight.UIGradient.Transparency = NumberSequence.new(0, 0)
-- update horizontal bar
end
end
Perfect, we have our health check and comparison structure down, now it’s time to update the UIGradient accordingly. Instead of writing the same code all over again, we will turn it into a function instead later.
We mentioned earlier that we have to line up the UIGradient’s rotation and transparency pattern. To do that, we have to get the alpha in order to get the position and rotation scale. Since we know each curved bar is 1/3 of circleMaxHealth, we have to get a value between 0-33.333.
local circleMaxHealth = 100
local Health, MaxHealth = 200, 200
local HealthBar = script.Parent:WaitForChild("HealthBar")
local function CurvedBarResize(bar, alpha)
-- code that will resize bar
end
local function UpdateHud()
local circleAlpha = circleMaxHealth / 3
local topRightAlpha = circleMaxHealth * (1/3)
local bottomRightAlpha = circleMaxHealth * (2/3)
if Health <= circleMaxHealth then
Health.Bar.Size = UDim2.new(0, 0, 0.12, 0)
if Health >= bottomRightAlpha then
HealthBar.TopLeft.UIGradient.Transparency = NumberSequence.new(0, 0)
HealthBar.TopRight.UIGradient.Transparency = NumberSequence.new(0, 0)
local alpha = (Health.Value - bottomRightAlpha) / circleAlpha -- Gets the 0-33.333 value of BottomRight and divides by circleAlpha
CurvedBarResize(HealthBar.BottomRight, alpha)
elseif Health >= topRightAlpha then
HealthBar.TopLeft.UIGradient.Transparency = NumberSequence.new(0, 0)
HealthBar.BottomRight.UIGradient.Transparency = NumberSequence.new(1, 1)
local alpha = (Health.Value - topRightAlpha) / circleAlpha -- Gets the 0-33.333 value of TopRight and divides by circleAlpha
CurvedBarResize(HealthBar.TopRight, alpha)
else
HealthBar.TopLeft.UIGradient.Transparency = NumberSequence.new(0, 0)
HealthBar.BottomRight.UIGradient.Transparency = NumberSequence.new(1, 1)
local alpha = Health.Value / circleAlpha -- Gets the 0-33.333 value of TopLeft and divides by circleAlpha
CurvedBarResize(HealthBar.TopLeft, alpha)
end
else
HealthBar.TopLeft.UIGradient.Transparency = NumberSequence.new(0, 0)
HealthBar.TopRight.UIGradient.Transparency = NumberSequence.new(0, 0)
HealthBar.BottomRight.UIGradient.Transparency = NumberSequence.new(0, 0)
-- update horizontal bar
end
end
And this is it, the final step to achieve the curved bars. I’ve mentioned earlier that the points in the middle of the NumberSequence are separated by a gap of 0.001, this is because in my testings, it resulted in ordering them randomly.
local circleMaxHealth = 100
local Health, MaxHealth = 200, 200
local HealthBar = script.Parent:WaitForChild("HealthBar")
local function CurvedBarResize(bar, alpha)
bar.UIGradient.Rotation = -90 * (1 - alpha) -- (1 - alpha) since we go backwards (from 0 to -90)
-- NumberSequence has to be in order, so I did some checks
if alpha - 0.001 <= 0 then -- We don't want a negative time value or 2 values on time = 0
bar.UIGradient.Transparency = NumberSequence.new(1, 1) -- The bar is empty
elseif alpha == 1 then -- We don't want to 2 values on time = 1
bar.UIGradient.Transparency = NumberSequence.new(0, 0) -- The bar is full
else
bar.UIGradient.Transparency = NumberSequence.new({
NumberSequenceKeypoint.new(0, 0),
NumberSequenceKeypoint.new(alpha - 0.001, 0),
NumberSequenceKeypoint.new(alpha, 1),
NumberSequenceKeypoint.new(1, 1)
})
end
end
local function UpdateHud()
local circleAlpha = circleMaxHealth / 3
local topRightAlpha = circleMaxHealth * (1/3)
local bottomRightAlpha = circleMaxHealth * (2/3)
if Health <= circleMaxHealth then
Health.Bar.Size = UDim2.new(0, 0, 0.12, 0)
if Health >= bottomRightAlpha then
HealthBar.TopLeft.UIGradient.Transparency = NumberSequence.new(0, 0)
HealthBar.TopRight.UIGradient.Transparency = NumberSequence.new(0, 0)
local alpha = (Health.Value - bottomRightAlpha) / circleAlpha
CurvedBarResize(HealthBar.BottomRight, alpha)
elseif Health >= topRightAlpha then
HealthBar.TopLeft.UIGradient.Transparency = NumberSequence.new(0, 0)
HealthBar.BottomRight.UIGradient.Transparency = NumberSequence.new(1, 1)
local alpha = (Health.Value - topRightAlpha) / circleAlpha
CurvedBarResize(HealthBar.TopRight, alpha)
else
HealthBar.TopLeft.UIGradient.Transparency = NumberSequence.new(0, 0)
HealthBar.BottomRight.UIGradient.Transparency = NumberSequence.new(1, 1)
local alpha = Health.Value / circleAlpha
CurvedBarResize(HealthBar.TopLeft, alpha)
end
else
HealthBar.TopLeft.UIGradient.Transparency = NumberSequence.new(0, 0)
HealthBar.TopRight.UIGradient.Transparency = NumberSequence.new(0, 0)
HealthBar.BottomRight.UIGradient.Transparency = NumberSequence.new(0, 0)
-- update horizontal bar
end
end
Phew, that’s all the hard part done. Now it’s time to resize the horizontal bar which will be a breeze. As mentioned earlier (and in the place I’ve provided), the bar’s size Y scale needs to be 0.12, parented inside the main frame that holds the 3 curved pieces.
Position it {0.5, 0}, {1, 0} with an anchor point of (1, 1) to line it up at the bottom center.
As for resizing the bar, we will scale it to the circleAlpha for size consistency throughout.
local circleMaxHealth = 100
local Health, MaxHealth = 200, 200
local HealthBar = script.Parent:WaitForChild("HealthBar")
local function CurvedBarResize(bar, alpha)
bar.UIGradient.Rotation = -90 * (1 - alpha)
if alpha - 0.001 <= 0 then
bar.UIGradient.Transparency = NumberSequence.new(1, 1)
elseif alpha == 1 then
bar.UIGradient.Transparency = NumberSequence.new(0, 0)
else
bar.UIGradient.Transparency = NumberSequence.new({
NumberSequenceKeypoint.new(0, 0),
NumberSequenceKeypoint.new(alpha - 0.001, 0),
NumberSequenceKeypoint.new(alpha, 1),
NumberSequenceKeypoint.new(1, 1)
})
end
end
local function UpdateHud()
local circleAlpha = circleMaxHealth / 3
local topRightAlpha = circleMaxHealth * (1/3)
local bottomRightAlpha = circleMaxHealth * (2/3)
if Health <= circleMaxHealth then
Health.Bar.Size = UDim2.new(0, 0, 0.12, 0)
if Health >= bottomRightAlpha then
HealthBar.TopLeft.UIGradient.Transparency = NumberSequence.new(0, 0)
HealthBar.TopRight.UIGradient.Transparency = NumberSequence.new(0, 0)
local alpha = (Health.Value - bottomRightAlpha) / circleAlpha
CurvedBarResize(HealthBar.BottomRight, alpha)
elseif Health >= topRightAlpha then
HealthBar.TopLeft.UIGradient.Transparency = NumberSequence.new(0, 0)
HealthBar.BottomRight.UIGradient.Transparency = NumberSequence.new(1, 1)
local alpha = (Health.Value - topRightAlpha) / circleAlpha
CurvedBarResize(HealthBar.TopRight, alpha)
else
HealthBar.TopLeft.UIGradient.Transparency = NumberSequence.new(0, 0)
HealthBar.BottomRight.UIGradient.Transparency = NumberSequence.new(1, 1)
local alpha = Health.Value / circleAlpha
CurvedBarResize(HealthBar.TopLeft, alpha)
end
else
HealthBar.TopLeft.UIGradient.Transparency = NumberSequence.new(0, 0)
HealthBar.TopRight.UIGradient.Transparency = NumberSequence.new(0, 0)
HealthBar.BottomRight.UIGradient.Transparency = NumberSequence.new(0, 0)
HealthBar.Bar.Size = UDim2.new((Health - circleMaxHealth) / circleAlpha, 0, 0.12, 0)
end
end
The black bar (the bar behind the health bar) will be the same concept but with MaxHealth instead. I’ll leave you to figure that out.
And there you have it! I hope this guide has helped and I hope it wasn’t too confusing. Maybe in the future we will get support for radial/coned gradients which will shrink this entire thing by 2/3.
Enjoy your new Kingdom Hearts Health bar!