I was wondering if it was possible to stop a coroutine (in my case, a timer) that has a yield, or is there any way to stop a loop that has a yield?
For example, if a timer is going on and a player leaves, is there a way to stop that loop (and ultimately stop the round)?
For example,
local myLoop = coroutine.wrap(function()
for i = 1, 60 do
wait(1)
end
end)
myLoop()
game.Players.PlayerRemoving:Connect(function()
myLoop.stop() -- where the loop would stop
end
You could create a boolean to say whether or not there is enough players and check if that bool is true within the loop. If it isnt true, break the loop. Something like this maybe? Sure there are other ways, and you can implement your logic within it but breaking the loop under a certain circumstance should do the job
edit: Completely forgot it was a coroutine, this will stop the loop within the coroutine my bad!
local myLoop = coroutine.wrap(function()
local enoughPlayers = true
for i = 1, 60 do
wait(1)
if not enoughPlayers then break end
game.Players.PlayerRemoving:Connect(function()
enoughPlayers = false
end)
end
end)
myLoop()
I was actually curious about this in the past and this post reminded me about it. After some searching, perhaps yielding a coroutine could solve this problem? Here is the official Lua documentation: https://www.lua.org/pil/9.1.html
Please test this and let me know if it works, as I am also curious.
I believe the issue with this is that it will wait until the wait() is over until termination, and the poster wants to terminate while the wait() is still ongoing.
The problem is that I don’t see it as a better alternative (in my case) than setting a variable with having enough players and the player that left (as @SkoobiDoobiDoo said). I’m just looking to see which player left to make a notification and send to the users, then end the round, breaking the loop.
I could just check every 0.1 seconds to see if there’s enough players and then set the second loop into a for loop with 10 iterations and a 0.1 second yield.
You can put the yield inside of the playerRemoving event, and that should end the coroutine immediately when a player leaves. With a boolean, you have to wait until the wait() is finished. For example, if you have:
for i = 1, 10 do
wait(100)
if boolean == false then
break
else
print(i)
end
end
This is an exaggeration but I am using it to show what I mean. It will wait 100 seconds before checking the boolean to terminate the function. However, it seems that you can immediately terminate the function by using coroutine.yield(coroutine). You can use the coroutine.yield() inside of the playerRemoving event, to immediately yield the coroutine even if it is during its wait(100). Meanwhile the other method will have to wait until the wait is finished to check the boolean.
I might also add that you won’t want to put the function that you access on termination within the coroutine. So if you have a function endGame() that is supposed to end the minigame, you wouldn’t want to put that within the coroutine you yield. That would yield as well and never end the game.
local myLoop = coroutine.wrap(function()
for i = 1, 100 do
wait(100)
game.Players.PlayerRemoving:Connect(function(plr)
coroutine.yield() -- doesn't seem to yield until that wait is over.
print(plr)
end)
end
end)
myLoop()
I haven’t yet found a way to terminate the loop and circumvent the wait(). There is likely a better way to achieve what you want without needing to do this.
Is there any reason you couldn’t connect the PlayerRemoving to a remote event which sends the notification?
Therefore it would send the notification and then terminate the loop when it gets the chance. I believe I may have been overcomplicating from the beginning and not understanding your question. @SkoobiDoobiDoo’s response would suffice if you do not need the countdown to terminate immediately, but you could still send the remote immediately.