Is there any way to check if two events have fired before doing something?

Hello, I was wondering if there was a more efficient way of doing this:

local doubleDown

tween1.Completed:Connect(function()
	if doubleDown then
		--do whatever happens when both events fire
	else
		doubleDown = true
	end
end)

tween2.Completed:Connect(function()
	if doubleDown then
		--do whatever happens when both events fire
	else
		doubleDown = true
	end
end)

It just doesn’t feel right. Is there a more efficient way to do this? I’ve googled this for a bit and didn’t find anything relevant.

Try to connect the events to the same function.

local doubleDown = false
function action()
	if doubleDown then
		--do whatever happens when both events fire
	else
		doubleDown = true
	end
end

tween1.Completed:Connect(action)
tween2.Completed:Connect(action)

This works, but is there any better way of waiting until two events fire to do something else? Do I have to use an external variable (in this case doubleDown) to wait until both events fire?

(edit: im great at typing)

Yeah, that’s pretty much how you do it. You let all of the events “check in” and do the action when the last of them completes.

I’m puzzled why you need this for tweens in particular, though.
If it’s certain that the tweens will always end at the same time, then just wait for only one of them.
If you know from the durations which tween will end later, just wait for the later tween.
If that’s too complicated (it can get complicated), then yes, go ahead and wait for both of them.


I also have to note that if you :Connect() to a tween, then the connection stays live after the tween is done. It won’t fire again if you just forget/never use that same tween instance again, but it’s something to keep in mind, especially if you do this to e.g. Touched events, which can and will run again immediately afterward.
So you’ll want to somehow disconnect the connections afterward, either by keeping the connections and disconnecting them as they fire, or using :Wait() to run only once (but stop the current thread/script).


Putting this here because I already wrote it so why not

This one waits for each event inline, without forcing you to continue all your stuff in a function:

local thisthread = coroutine.running()
local function action()
	coroutine.resume(thisthread)
end
tween1.Completed:Connect(action)
tween2.Completed:Connect(action)
coroutine.yield()
coroutine.yield()
--do whatever happens when both events fire

(coroutine.yield() will pause this thread like task.wait() or any other async function do, except it will only wake when it is coroutine.resume()d, which is what the tweens will do)

This function just lets you wait for a list of connections:

local function waiter(signal, coro)
	signal:Wait()
	return coroutine.resume(coro)
end
local function waitForAll(...)
	local signals = {...}
	local this = coroutine.running()
	for signal in ipairs(signals) do
		coroutine.wrap(waiter)(signal, this)
	end
	for i = 1, #signals do
		coroutine.yield()
	end
end

waitForAll(tween1.Completed, tween2.Completed)
--do whatever happens when both events fire
waitForAll(workspace.Part1.Touched, workspace.Part2.Touched, workspace.Part3.Touched)
-- if you want this but even better, use Promises