What I want to happen :
The countdown resets to 60 immediately after I leave the circle and the loop stops running in order for the timer to completely reset.
What happens:
Code (Runs every time a specified part is touched):
local normCD = 60
local function startNormCountDown()
if normMinQueue == normPlayersQueued then
local countdown = normDisplay.SurfaceGui.Frame.Countdown
for i = 60,0,-1 do
if normPlayersQueued >= normMinQueue then
normCD = i
countdown.Text = normCD
else
normCD = 60
countdown.Text = normCD
break
end
task.wait(1)
end
end
end
At the end, I see you staying on the circle, which is the problem; Add a Touched and ToucheEnded event, so it won’t glitch and only fire when the Touched event gets registered.
if I were you, rather than running a function every time the function is called. I would use GetTouchingParts every second or few seconds. https://developer.roblox.com/en-us/api-reference/function/BasePart/GetTouchingParts
As you currently have it, spamming it can cause the same function to be running in synchronous, which would allow one to try to cancel it, and then an instant later another one continues the count, which is just problematic.
I won’t write a whole program example, but here’s an explaination:
Have a loop which runs the same code every second or few seconds. Within that create a variable, for example touchingParts and set it to the return of :GetTouchingParts on the part which can be touched (if that makes sense).
Then, create a table which you will fill with player objects. Once that is done, iterate through the list of parts and if part.Parent and Players:GetPlayerFromCharacter(part.Parent), then add that player to the table. Do this for every part. If the part is the child of a player’s character, then before adding the player to the table, use .find to see if that player is in the table already (will return nil if they aren’t). At that point, you’ll have a list of players which you can use for your playerlist Gui. You can then also have the same code from the function you used. That code works, the problem is that it runs multiple times as a result of the event. This option avoids the event.
The “.Touched” and “.TouchEnded” events are quite inaccurate (they will fire repetitively even if it appears as if the touching parts never stopped touching). Consider using “GetPartsInPart()” or “GetTouchingParts()” instead.
Here’s an example script.
local Run = game:GetService("RunService")
local Players = game:GetService("Players")
local Part = script.Parent
local Timer = 60
local function OnStepped(Time, Step)
local TouchingParts = workspace:GetPartsInPart(Part)
for _, TouchingPart in ipairs(TouchingParts) do
local TouchingModel = TouchingPart:FindFirstAncestorOfClass("Model")
if TouchingModel then
local TouchingPlayer = Players:GetPlayerFromCharacter(TouchingModel)
if TouchingPlayer then
Timer -= Step
if Timer <= 0 then
Timer = 60
return
end
else
print(Timer)
Timer = 60
end
else
print(Timer)
Timer = 60
end
end
end
Run.Stepped:Connect(OnStepped)