I am trying to make a GUI that displays the health of a vehicle by using a humanoid.
I put a Car.Humanoid.Changed:connect(function() to do stuff with the GUI after detecting health change, however, this wouldn’t work because Car is not defined yet because the player is not in any vehicle. I tried to solve this by checking if a Car variable is true in a while loop before doing the :connect, and set the Car variable to true when the player’s humanoid is detected seated. However this didn’t work as well and now i am lost.
local Car = false
delay(0, function()
while Car do
print("car is true")
Car.Humanoid.Changed:connect(function()
if Car.Humanoid.Health == math.huge then --God(Same as full health color but with infinity health)
--does stuff to gui
else
--does stuff to gui
end
end)
end
end)
--Detect when the player is in a vehicle
Character.Humanoid.Seated:Connect(function()
if Character.Humanoid:GetState() == Enum.HumanoidStateType.Seated then
if Character.Humanoid.SeatPart.Parent.Name == "Passenger Seats" then
Car = true
end
else
Car = false
end
end)
First off, this is not how loops work. That while loop is going to yield your code until it finishes, and since there is no finish, it will just crash your game completely. Loops run really fast, for example you can have a for loop do 100 cycles in just a single frame. Now what do you think happens when you tell a loop to run infinite amounts of times? Yes, it will crash.
Also, the .Changed event fires whenever a change happens to your instance. If you connect lets say 3 different Changed events to the same instance, then all 4 of those functions will run at the same time when the change happens. In your script, you connect this changed event in a loop over and over, so the code inside the function will run thousands of times.
Here’s what you i suggest:
The same way events can be connected, they can also be disconnected. You can create a variable beforehand and then assign the Event to that variable, then you’ll be able to disconnect it any time like this:
local myFunction
myFunction = Humanoid.Health.Changed:Connect(function()
-- stuff here
end)
myFunction:Disconnect() -- This disconnects the Changed event so it doesn't fire anymore when you take damage
And you can use it in your script like this:
local changedEvent
Character.Humanoid.Seated:Connect(function()
if Character.Humanoid:GetState() == Enum.HumanoidStateType.Seated then
if Character.Humanoid.SeatPart.Parent.Name == "Passenger Seats" then
Car = true
changedEvent = Car.Humanoid.Changed:connect(function()
if Car.Humanoid.Health == math.huge then
--does stuff to GUI
else
--does stuff to GUI
end
end)
end
else
Car = false
changedEvent:Disconnect()
end
end)
Also, I don’t know what the variable Car is, but if its a boolean (as you set it to true and false), you wont be able to write Car.Humanoid as a boolean variable cant have child instances.
That yield is exactly what impacts performance. Yielding just makes your code “stop”, but it checks back every frame to see if it can continue running or not. And if you do that in a loop, then the yielding will never end, because as it continues again, another :Wait will be created. So it would exhaust the script the same way as if you run the loop every frame.
local int = Instance.new("IntValue",workspace) --parent it (this is bad practice)
while true do
int.Changed:Wait()
print("it was CHANGED")
end
That print will print each time it changes, not every frame like you’d suggest. Your statement would be true for Connect or Once, but not Wait, since Wait will yield the while loop, which is NOT a spawned coroutine.
The loop stops at Wait. When the change happens, it continues. To see if the change happened, the code checks every frame. And since it checks every time if it has changed, it works like a loop checking it. Yes, it will only print when it actually changed, but until then the code has to check if it did continuously.
Plus the whole script will be yielded until it happens. It might even limit its functionality. And using a loop like that will make it a “disposable” script as the loop will only work once. If it finishes and the player enters the car again, nothing will happen.
Exactly, but that frame checking performance is not nearly as bad as you might think. Try benchmarking it.
It needs to be a while true loop in order for the code design to work properly. If the loop breaks, then it will need to be restarted in order for the code to work properly.