I made a custom health system and I have a ui above players that displays what that custom health value is that gets updated by a server script while loop.
My first problem is that the script breaks because it can’t find the ui right away, and I can’t figure out how to make it wait for the ui to be assigned to the player.
My second problem is that changing the players health values in a local script doesn’t update them for the server, so the server is stuck reading the value the player is assigned upon joining the server unless I somehow update them using the server script.
while true do
local Players = game.Players:GetChildren()
for i,v in pairs(Players) do
v.Character:WaitForChild("OverheadGui").HealthValue.Text = v.Health.Value
You got some options to update your Overhead Gui that includes:
Using the PlayerAdded event with CharacterAdded & Humanoid.Health.Changed.
Using a Remote Event by firing an event from the player to the server telling it to update their Overhead.
Using some sort of looping to update the Overhead Gui for every player without any additional event like what you’ve did with some changes of course.
Personally, I’d recommend using the first method (safe, server validation, more efficient than looping)
Anyways, for your problem which you’ve used a while loop, you don’t need to use WaitForChild method as you’re already looping nearly every frame to update every existing player’s Overhead Gui.
You should use FindFirstChild and its equivalents (not yielding and safe to use for referring instances that could be nil) like the following code which does:
Check for the player’s character (if there is no character, the loop skips that player).
Check for the Overhead Gui existence (if there is no Gui, the loop skips to the next player)
-- side note: ipairs is better for arrays.
for i,v in ipairs(Players) do
if not Player.Character then continue end --| Validation for the player character
local TargetTextLabel = v.Character:FindFirstChild("OverheadGui"):FindFirstChild("HealthValue")
if not TargetTextLabel then continue end --| Validation for the Overhead Gui.
TargetTextLabel.Text = tostring(v.Health) --| Health to string.
Its better to Update the Players overhead ui with the Server rather than the client
The Client (If you dont know)
Only updates stuff in which are visible to the Player, so updating Values isnt ideal and wont save due to the Server not recognizing it.
You would commonly use ServerScriptService to update or add every players UI, or StarterCharacterScripts to add the UI to the character and update it from there
local Players = game.Players
local UI = "Your UI" -- insert your UI here
-- Code to Insert Ui
local Player = game.Players:GetPlayerFromCharacter(script.Parent)
local char = script.Parent
local UI = "Your UI" -- put your UI here
-- code to insert UI
If you want to Update the UI when a stats of the players is changed, you would use: Example:GetPropertyChangedSignal("Value"):Connect()
This will Traget that specific Property for changes
If you want to update the UI when a specific Property (including its value) is changed, then you would put Example.Changed:Connect()
This is so that the Server doesnt waste as much resources using a while loop.
About the Variables, its better to use WaitForChild for this case as it waits until the specified object exists, using FindFirstChild will look for the Object, but if it isnt found, it will return nil,
So in All, This is really all you need to do:
local Players = game.Players
local UI = "YourUI" -- Replace with your UI
Players.PlayerAdded:Connect(function(plr) -- When Player is added
plr.CharacterAdded:Connect(function(char) -- When Character is Added
local Humanoid = char:WaitForChild("Humanoid") -- Humanoid
local Clone = UI:Clone() -- Clones UI
Clone.Parent = char:WaitForChild("HumanoidRootPart") -- Assigns the Clone to the Characters "PrimaryPart"
Clone.HealthValue.Text = tostring(Humanoid.Health) -- Converts the Players Health to a string for the Text (Optional)
Humanoid:GetPropertyChangedSignal("Health"):Connect(function() -- Used to detect change rather than using a loop which wastes rescources
Clone.HealthValue.Text = tostring(Humanoid.Health) -- Changes the Text when Health has changed
I assigned IntValues to the player to use for the custom health system, not the humanoids base 100 health, although I was still able to get what you recommended to work with the loop.
As for the values themselves, I set up a local script to allow the player to increase or decrease the values manually, but the problem is that doing so only updates them for that specific player and not for the server, meaning the loop still displays the values that were first assigned when the player joins