Overhead ui problems

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.

wait(5)
while true do
	local Players = game.Players:GetChildren()
	
	for i,v in pairs(Players) do

		v.Character:WaitForChild("OverheadGui").HealthValue.Text = v.Health.Value
	end
	wait()
end

It would be the best to create a LocalScript that reads players health from server when changed event and change the bars on client side.

Okay so…
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.
end
Forgot to say that you are using the player health with a wrong way... Player health is a number, you just need to convert it to a string value using `tostring()`

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

ServerScriptService:

local Players = game.Players
local UI = "Your UI" -- insert your UI here

Players.PlayerAdded:Connect(function(player)
  player.CharacterAdded:Connect(function(char)
  -- Code to Insert Ui
   end)
end)

StarterCharacterScripts:

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
      end)
   end)
end)

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

You’d have to assign and control the values server side then.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.