local function updateHealth(health)
HealthBar.Bar:TweenSize(UDim2.new(health / Humanoid.MaxHealth, 0, 1, 0), Enum.EasingDirection.Out, Enum.EasingStyle.Linear, 0.25, true)
HealthBar.Health.Text = health
end
Humanoid.HealthChanged:Connect(updateHealth)
Which is fine, however, when a player dies, and respawns, the UI stays at saying their health is 0. The UI.ResetOnSpawn is set to false. I CAN NOT change this, due to other sections in the UI’s code. This property has to remain.
So is there any other way I can detect a players health, without resorting to while loops or using RunService to constantly check
There are two methods; Connect it to a character added event:
local function updateHealth(health)
HealthBar.Bar:TweenSize(UDim2.new(health / 100, 0, 1, 0), Enum.EasingDirection.Out, Enum.EasingStyle.Linear, 0.25, true)
HealthBar.Health.Text = health
end
game.Players.LocalPlayer.CharacterAdded:Connect(function(char)--Every time there is a new character, bind the event
char:WaitForChild('Humanoid').HealthChanged:Connect(updateHealth)
end)
Or update the health every frame:
local function updateHealth(health)
HealthBar.Bar:TweenSize(UDim2.new(health / 100, 0, 1, 0), Enum.EasingDirection.Out, Enum.EasingStyle.Linear, 0.25, true)
HealthBar.Health.Text = health
end
game:GetService('RunService').RenderStepped:Connect(function()
local plr = game.Players.LocalPlayer
if plr.Character then
updateHealth(plr.Character:WaitForChild('Humanoid').Health)
end
end)
Disclaimer: This was typed on mobile so I apologize for any typos or autocorrects that may have occured. Thank you.
Create a seperate gui?
You shouldn’t need to put everything under one screen gui.
If you did still want to keep it under one screen gui then you could just change the humanoid variable, disconnect the previous health changed event, and create a new HealthChanged event for the new humanoid every time CharacterAdded fires.
Why would you make a sperate gui? You could still reuse the old one. Also, this would not help solve the problem but would make it worse.
Also, just side note but connections connected to a nil object will disconnect via garbage collection (very few exceptions, this example should be fine)
The question asked was “How do I detect the new humanoid’s health”. Adding Guis has NOTHING to do with the question. That is what I meant by “this would not help the problem”.
As mentioned in the OP, he can’t set ResetOnSpawn to true because of other things in the same GUI, so if he made another gui then he could set ResetOnSpawn to true for that specific gui with the health bar which should fix the issue.
game:GetService('RunService').RenderStepped:Connect(function()
local Character = Player.Character or Player.CharacterAdded:Wait()
local Humanoid = Character:WaitForChild('Humanoid')
local Health = math.floor(Humanoid.Health + 0.5)
HealthBar.Bar:TweenSize(UDim2.new(Health / Humanoid.MaxHealth, 0, 1, 0), Enum.EasingDirection.Out, Enum.EasingStyle.Linear, 0.25, true)
HealthBar.Health.Text = Health
end)
Doesn’t seem like the most efficient way to do this??
That would be pretty inefficient since you’ll have a large number of yielding functions waiting on a character being added at certain points considering the function is being called with render stepped.
It would be much better to instead have a connection for when the character is added and then connect the health changed to the new humanoid. This is how I would do it:
local Humanoid
local function updateHealth(health)
HealthBar.Bar:TweenSize(UDim2.new(health / Humanoid.MaxHealth, 0, 1, 0), Enum.EasingDirection.Out, Enum.EasingStyle.Linear, 0.25, true)
HealthBar.Health.Text = health
end
function NewCharacter(c)
Humanoid = c:WaitForChild("Humanoid")
Humanoid.HealthChanged:Connect(updateHealth)
end
Player.CharacterAdded:Connect(NewCharacter)
-- in hindsight its possible the character may already exist in which case you would call the function on the current character
if Player.Character then
NewCharacter(Player.Character)
end
The other option would be to just not tween it while the player doesn’t have a character and if the player does have a character, tween the health, dynamically using the player’s current character and humanoid in the render stepped function. Whatever you do just don’t yield the renderstepped function for an event.
Edit: That is what RealTimothy0812 was suggesting, you were just implementing incorrectly.
Have you tried this way to detect a players health, it seems to work perfect for me:
local player = game.Players.LocalPlayer
local healthBar = script.Parent:WaitForChild("HealthBar")
local hum = player.Character:WaitForChild("Humanoid")
player.Character:WaitForChild("Humanoid").Changed:Connect(function(Type)
if Type == "Health" then
healthBar.ProgressBar:TweenSize(UDim2.new(hum.Health / hum.MaxHealth, 0, 1, 0), "Out", "Linear", 0.25, true)
healthBar.HealthText.Text = tostring(math.floor(hum.Health) .. "/" .. math.floor(hum.MaxHealth))
end
end)
That won’t work for OP’s use case because they’re putting it inside a LayerCollector with RespawnOnSpawn as false. This will just try to reference the character’s old character and humanoid for as long as the script is present.
My opinion, the way that pops up in my head is to create a module script in ReplicatedFirst/Storage and then requiring it in the GUI to update the players health
I do this by forcefully activating the tween at the start of the script,so it runs everytime the player respawns.Like this.
HealthBar.Bar:TweenSize(UDim2.new(health / Humanoid.MaxHealth, 0, 1, 0), Enum.EasingDirection.Out, Enum.EasingStyle.Linear, 0.25, true)
HealthBar.Health.Text = health
--tween as the script reads for the first time(when the player respawns).
local function updateHealth(health)
HealthBar.Bar:TweenSize(UDim2.new(health / Humanoid.MaxHealth, 0, 1, 0), Enum.EasingDirection.Out, Enum.EasingStyle.Linear, 0.25, true)
HealthBar.Health.Text = health
end
Humanoid.HealthChanged:Connect(updateHealth)
--The rest of your script.
Unless your script doesn’t reset upon death,this should work.