I have been searching for ways to do this, but i cant seem to find a solution.
So i was wandering how i can instantly cancel a function/event. I’ve tried using :Disconnect()with a :Connect event, but i think Disconnect doesn’t instantly Disconnect the event.
I also want the function/event to be cancelled outside of it.
There are alternatives to cancelling it, such as using an if statement around the function (so the event would be called, but the function wouldn’t run). If that doesn’t work for you, please explain why, as that may help people come up with solutions.
So the function runs code off a module script. There is code outside the function checking the amount of players with a value. If this code detects less than 2 players with the value, i want it to immediately cancel or disconnect the function.
This wouldn’t work because the code outside the function needs to be the one affecting the function, not an if statement inside the actual function. This is because the code outside the function constantly checks for the amount of players with the value, while the if statement doesn’t.
There is actually a way to disconnect outside of the function. Here’s a quick example I created.
count = 0
local c = script.Parent.Touched:Connect(function()
count = count + 1
end)
while true do
wait()
if count >= 5 then
c:Disconnect()
end
end
It does seem to disconnect right when it gets to five for me, but it could depend on how many times you are firing the function in a matter of seconds.
Why would you need to cancel a function half-way through? I’m sure you can, but it’ll be messy and there’s probably a better way of writing your code out so it doesn’t need to do this.
If you prefer, i can explain to you what this does.
script:
local RoundFunction = require(script.RoundFunctions)
local ReplicatedStorage = game:WaitForChild("ReplicatedStorage")
local Values = ReplicatedStorage:WaitForChild("Values")
local IntermissionTimer = Values:WaitForChild("IntermissionTimer")
local IntermissionConnect1 = script:WaitForChild("IntermissionConnect1")
local IsIntermission = false
local IntermissionDone = false
local Intermission = IntermissionConnect1:GetPropertyChangedSignal("Value"):Connect(function()
print("Start")
wait(0.25)
IsIntermission = true
RoundFunction.IntermissionTimer(10)
IntermissionDone = true
end)
game.ReplicatedStorage.RemoteEvents.AvailablePlayers.OnServerEvent:Connect(function()
if IntermissionDone == false then
local AvailablePlayers = RoundFunction.InsertReadyPlayers()
if #AvailablePlayers <1 then
if IsIntermission then
IsIntermission = false
Intermission:Disconnect()
end
if #AvailablePlayers == 0 then
IntermissionTimer.Value = "2 Ready Players Required"
elseif #AvailablePlayers == 1 then
IntermissionTimer.Value = "1 Ready Player Required"
else
print("Error")
end
elseif #AvailablePlayers >= 1 then
if not IsIntermission then
if IntermissionConnect1.Value then
IntermissionConnect1.Value = false
elseif not IntermissionConnect1.Value then
IntermissionConnect1.Value = true
else
print("Error")
end
end
end
end
end)
ModuleScript:
local module = {}
local ReplicatedStorage = game:WaitForChild("ReplicatedStorage")
local Values = ReplicatedStorage:WaitForChild("Values")
local IntermissionTimer = Values:WaitForChild("IntermissionTimer")
function module.InsertReadyPlayers()
local AvailablePlayers = {}
for i,v in pairs(game.Players:GetPlayers()) do
local PlayerGui = v:WaitForChild("PlayerGui")
local Values = PlayerGui:WaitForChild("Values")
local Ready = Values:WaitForChild("Ready")
if Ready.Value then
if not table.find(AvailablePlayers,v)then
table.insert(AvailablePlayers,v)
end
elseif not Ready.Value then
if table.find(AvailablePlayers,v)then
table.remove(AvailablePlayers,i)
end
else
print("Error")
end
end
return AvailablePlayers
end
function module.IntermissionTimer(Seconds)
local Interrupted = false
for i = Seconds,0,-1 do
IntermissionTimer.Value = "Intermission: "..i
wait(1)
end
end
If it’s something like an infinite loop within the function, disconnecting the listener will cause it to stop listening for the event - but the loop will keep running, so in that case you could: every iteration check for some sort of variable at the beginning of the block, and only run the code if the variable’s value is true, so you could set the value to false after disconnecting.
No the iteration if it was infinite, will keep running in a thread - disconnecting a listener only allows you to unsubscribe to an event so that firing it again (after disconnecting obviously) won’t let the callback passed to the listener run.
local active = true
-- your function
coroutine.wrap(function()
while true do
if not active then coroutine.yield() end -- you could use break too
-- do your stuff within
end
end)()
wait(5)
active = false
Since Connections are just functions, you can call return to instantly stop the function, returning nothing to the event handler.
local function HandleNoob(p)
if p.UserId == 8094244 then
return --do nothing (cancel the event)
end
print("Noob Inbound!")
end
Players.PlayerAdded:Connect(HandleNoob)
I’m trying to make an intermission system, where two people with values set to true (changed with a button) are required for it to start, and if in between the intermission, one decided to leave, the intermission cancels.
I did this successfully by adding if statements and for loops checking that at least 2 players have this value set to true, and making the function run again (by calling it again). However, i found this really messy, so i redesigned the system so that it would only check the players everytime someone pressed the button, and if there were less than 2, cancel the intermission.
So that’s where i am now. I’m trying to make it cancel the intermission when there are less than 2 players with this value set to true.
(Basically in short, i don’t want to use the method you provided me because that would mean i have to stuff my code full of if statements and for loops constantly checking the players).
task.cancel()
Is a good way to cancel it mid function, disconnecting the event wouldn’t stop it if it had already started.
task.cancel() would stop it no matter what.
That’s not how cancel works. Cancel prevents the thread from being resumed by the task scheduler which relies on it being in a yielding state. A thread will continue to run if it was executed by the task scheduler and cancelling it won’t abort the thread’s resumption.
Yes, task.spawn creates a thread, the function you spawned will be handled entirely on this thread.
if you use task.cancel to cancel that thread the function you spawned will stop.
I have always used it this way and never had any problems.
The description on creator hub is a bit vague in my opinion but I do think that closing a thread means it stops the function inside of it.