In short
In a LocalScript in StarterPlayerScripts, hide the default bar with StarterGui:SetCoreGuiEnabled(Enum.CoreGuiType.Health, false), build a ScreenGui with a background frame and a fill frame, and on Humanoid.HealthChanged set the fill's width to Health / MaxHealth. Connect again on CharacterAdded, because each respawn brings a new Humanoid.
- Set the ScreenGui's
ResetOnSpawnto false and reconnect to the new Humanoid, so the bar never flickers on respawn. - Tween the width for a smooth slide, and blend the colour from red to green with
Color3:Lerp. - Health shown on screen is read only. Damage and healing happen on the server.
Get the script
Custom health bar GUI script
One LocalScript hides Roblox's health bar and shows a bigger one with numbers that slides and turns from green to red as the player loses health.
-- LocalScript in StarterPlayerScripts named HealthBar.
-- Replaces Roblox's health bar with a bigger one that shows numbers, slides when
-- health changes and turns from green to red.
local Players = game:GetService("Players")
local StarterGui = game:GetService("StarterGui")
local TweenService = game:GetService("TweenService")
local FULL_COLOR = Color3.fromRGB(70, 220, 110)
local EMPTY_COLOR = Color3.fromRGB(235, 60, 60)
local HIDE_DEFAULT = true -- hide Roblox's own health bar
local player = Players.LocalPlayer
if HIDE_DEFAULT then
StarterGui:SetCoreGuiEnabled(Enum.CoreGuiType.Health, false)
end
local gui = Instance.new("ScreenGui")
gui.Name = "HealthGui"
gui.ResetOnSpawn = false
local back = Instance.new("Frame")
back.AnchorPoint = Vector2.new(0.5, 1)
back.Position = UDim2.new(0.5, 0, 1, -56)
back.Size = UDim2.fromOffset(300, 26)
back.BackgroundColor3 = Color3.fromRGB(30, 26, 40)
back.Parent = gui
local fill = Instance.new("Frame")
fill.Size = UDim2.fromScale(1, 1)
fill.BackgroundColor3 = FULL_COLOR
fill.BorderSizePixel = 0
fill.Parent = back
for _, frame in { back, fill } do
local corner = Instance.new("UICorner")
corner.CornerRadius = UDim.new(0, 8)
corner.Parent = frame
end
local label = Instance.new("TextLabel")
label.Size = UDim2.fromScale(1, 1)
label.BackgroundTransparency = 1
label.TextColor3 = Color3.new(1, 1, 1)
label.TextStrokeTransparency = 0.5
label.Font = Enum.Font.GothamBold
label.TextSize = 16
label.ZIndex = 2
label.Parent = back
gui.Parent = player:WaitForChild("PlayerGui")
local slide = TweenInfo.new(0.25, Enum.EasingStyle.Quad, Enum.EasingDirection.Out)
local function show(humanoid: Humanoid)
local max = math.max(humanoid.MaxHealth, 1)
local fraction = math.clamp(humanoid.Health / max, 0, 1)
TweenService:Create(fill, slide, {
Size = UDim2.fromScale(fraction, 1),
BackgroundColor3 = EMPTY_COLOR:Lerp(FULL_COLOR, fraction),
}):Play()
label.Text = string.format("%d / %d", math.ceil(humanoid.Health), math.ceil(max))
end
local function onCharacter(character: Model)
local humanoid = character:WaitForChild("Humanoid") :: Humanoid
show(humanoid)
humanoid.HealthChanged:Connect(function()
show(humanoid)
end)
humanoid:GetPropertyChangedSignal("MaxHealth"):Connect(function()
show(humanoid)
end)
end
if player.Character then
onCharacter(player.Character)
end
player.CharacterAdded:Connect(onCharacter)
RoCode builds it in the place you have open in Roblox Studio, on Windows or macOS with a desktop browser; on a phone the button sends the prompt and the link to your computer. Free to start, with free credits every day. More Roblox Studio scripts
Where to put it
StarterPlayer
StarterPlayerScripts
HealthBar LocalScript new
Settings you can change
HIDE_DEFAULTIn the script- Hide Roblox's own health bar. Set to
falseto show both. Default:true. FULL_COLORIn the script- The colour at full health. EMPTY_COLOR on the next line is the colour near 0. Default:
Color3.fromRGB(70, 220, 110).
Type-checked with luau-lsp strict against Roblox's API definitions on 23 October 2026. Not playtested in Studio yet: press Play and watch the Output window before you publish.
Prompt for RoCode
Replace the default health bar with a custom one: a LocalScript that hides the CoreGui health bar and shows a 300 pixel bar at the bottom center with the health as numbers, sliding smoothly when health changes and fading from green to red, and that keeps working after respawning.
On this page
How the health bar works
Health lives on the character's Humanoid: Health and MaxHealth, 100 and 100 by default. The server changes Health when a player takes damage, and the new value reaches the player's device, where HealthChanged fires. A bar is two frames: a dark background, and a fill inside it whose width is the fraction of health left.
| Object | Size | Job |
|---|---|---|
back Frame | 300 by 26 pixels | The dark track. |
fill Frame | Health / MaxHealth wide | The coloured part. |
label TextLabel | Same as the track | The numbers, such as 65 / 100. |
Step 1: Add the health bar
Insert a LocalScript in StarterPlayer > StarterPlayerScripts named HealthBar:
-- LocalScript in StarterPlayerScripts named HealthBar.
-- Replaces Roblox's health bar with a bigger one that shows numbers, slides when
-- health changes and turns from green to red.
local Players = game:GetService("Players")
local StarterGui = game:GetService("StarterGui")
local TweenService = game:GetService("TweenService")
local FULL_COLOR = Color3.fromRGB(70, 220, 110)
local EMPTY_COLOR = Color3.fromRGB(235, 60, 60)
local HIDE_DEFAULT = true -- hide Roblox's own health bar
local player = Players.LocalPlayer
if HIDE_DEFAULT then
StarterGui:SetCoreGuiEnabled(Enum.CoreGuiType.Health, false)
end
local gui = Instance.new("ScreenGui")
gui.Name = "HealthGui"
gui.ResetOnSpawn = false
local back = Instance.new("Frame")
back.AnchorPoint = Vector2.new(0.5, 1)
back.Position = UDim2.new(0.5, 0, 1, -56)
back.Size = UDim2.fromOffset(300, 26)
back.BackgroundColor3 = Color3.fromRGB(30, 26, 40)
back.Parent = gui
local fill = Instance.new("Frame")
fill.Size = UDim2.fromScale(1, 1)
fill.BackgroundColor3 = FULL_COLOR
fill.BorderSizePixel = 0
fill.Parent = back
for _, frame in { back, fill } do
local corner = Instance.new("UICorner")
corner.CornerRadius = UDim.new(0, 8)
corner.Parent = frame
end
local label = Instance.new("TextLabel")
label.Size = UDim2.fromScale(1, 1)
label.BackgroundTransparency = 1
label.TextColor3 = Color3.new(1, 1, 1)
label.TextStrokeTransparency = 0.5
label.Font = Enum.Font.GothamBold
label.TextSize = 16
label.ZIndex = 2
label.Parent = back
gui.Parent = player:WaitForChild("PlayerGui")
local slide = TweenInfo.new(0.25, Enum.EasingStyle.Quad, Enum.EasingDirection.Out)
local function show(humanoid: Humanoid)
local max = math.max(humanoid.MaxHealth, 1)
local fraction = math.clamp(humanoid.Health / max, 0, 1)
TweenService:Create(fill, slide, {
Size = UDim2.fromScale(fraction, 1),
BackgroundColor3 = EMPTY_COLOR:Lerp(FULL_COLOR, fraction),
}):Play()
label.Text = string.format("%d / %d", math.ceil(humanoid.Health), math.ceil(max))
end
local function onCharacter(character: Model)
local humanoid = character:WaitForChild("Humanoid") :: Humanoid
show(humanoid)
humanoid.HealthChanged:Connect(function()
show(humanoid)
end)
humanoid:GetPropertyChangedSignal("MaxHealth"):Connect(function()
show(humanoid)
end)
end
if player.Character then
onCharacter(player.Character)
end
player.CharacterAdded:Connect(onCharacter)
The bar is built once, with ResetOnSpawn = false so it stays through deaths. onCharacter runs for the first character and every respawn, finds the new Humanoid and connects to it. show tweens the fill's width to the health fraction over a quarter of a second and blends its colour from EMPTY_COLOR to FULL_COLOR. It also listens for MaxHealth changes, so a 200 health power-up shows correctly.
To design the bar in Studio instead, build the same frames in a ScreenGui in StarterGui, then find them from this script with WaitForChild and keep the show and onCharacter functions.
Step 2: Health bars above heads
Roblox already draws a small health bar above other players when they are hurt. These Humanoid properties control it:
| Property | What it changes |
|---|---|
Humanoid.HealthDisplayType | When the bar shows: only when damaged, always, or never. |
Humanoid.HealthDisplayDistance | How far away other players can see it. |
Humanoid.DisplayDistanceType | Whether the name and bar show to viewers, to the subject, or not at all. |
For a styled bar above heads, such as a boss bar, add a BillboardGui to the character's head with the same two frames, and update it from a script the same way.
Test it
- Press Play. The bar at the bottom shows 100 / 100 and Roblox's own bar is gone.
- Take damage, for example from a damage brick: the bar slides down and shifts toward red.
- Die and respawn: the bar goes back to full and keeps working.
Common errors and fixes
If the bar does not move, check the Output window for an error from HealthBar.
The bar never changes
The script must be a LocalScript in StarterPlayerScripts. If you changed it to put the bar in StarterGui, check it reconnects to the new Humanoid after a respawn.
The default health bar still shows
SetCoreGuiEnabled only works from a LocalScript. Check HIDE_DEFAULT is true and nothing else turns the health bar back on.
The bar is stuck after I respawn
It is still listening to the old Humanoid. Connect again in CharacterAdded, as the script does.
Changing health in the Properties window does nothing
In a playtest, change the Humanoid's Health on the Server view. A change on the Client view is not how damage arrives in a real game.
Build it with RoCode
If you would rather not set this up by hand, RoCode can build it in the place you have open. RoCode is an independent AI agent for Roblox Studio, not made by Roblox: you describe the change in a web chat, and its Studio plugin creates the scripts and GUI in your Explorer.
Replace the default health bar with a big bar at the bottom of the screen showing the numbers, red when low and green when full, with a smooth slide.
- Writes the health bar LocalScript, or builds the GUI objects in StarterGui if you want to style them in Studio
- Can insert a ready-made HUD from its premium UI kits in one step, with coins, gems and a side menu, in one of five themes (candy, neon, gold, blocky, pastel)
- Is told to compile-check each script with Check Script, and sets undo points around each batch
After a build, RoCode can run its test robot: it plays your game in Studio and reports PASS or FAIL. It checks only what it chose to test, so look at the bar on a phone screen size yourself. How RoCode connects to Studio.
Questions
How do I make a custom health bar in Roblox?
Build two frames in a ScreenGui and, on Humanoid.HealthChanged, set the inner frame's width to Health divided by MaxHealth. Step 1 has a complete LocalScript.
How do I hide the default health bar?
From a LocalScript: game:GetService("StarterGui"):SetCoreGuiEnabled(Enum.CoreGuiType.Health, false).
Why does my health bar stop working after I die?
Respawning creates a new Humanoid. Reconnect to it in player.CharacterAdded.
How do I change max health?
On the server, set humanoid.MaxHealth and then humanoid.Health to the new value. The bar follows both.
Sources and further reading
- Roblox Creator Docs: StarterGui:SetCoreGuiEnabled. hiding the default health bar
- Roblox Creator Docs: Humanoid. Health, MaxHealth, HealthChanged and the overhead display properties
- Roblox Creator Docs: TweenService. the sliding fill
How the code was checked: every script on this page passes Luau's strict type checker against Roblox's API definitions (luau-lsp, 23 October 2026). A type check catches misspelt APIs and wrong types, not game logic, so playtest in Studio before you publish.