Waiting for multiple events simultaneously

Lets say I want to get from Point A to Point B. To do this, one of two things has to happen:

  1. The character dies
  2. OR the character respawns

What’s the most effective way to wait for this?

Desired method (doesn’t work)

local completed = player.CharacterAdded:Wait() or humanoid.Died:Wait()

Current Method

local bindable = Instance.new("BindableEvent")
local events = {
	Died = humanoid.Died:Connect(function()
		bindable:Fire()
	end);
	Added = player.CharacterAdded:Connect(function()
		bindable:Fire()
	end);
}
local completed = bindable.Event:Wait()
for _, event in pairs(events) do
	event:Disconnect()
end
events = nil
bindable:Destroy()
1 Like

Maybe a changed event on the Player object? Don’t know if you can with the character and get the same result. Do remember to disconnect the event directly after you get what you want, and use a debounce and checks to be sure it’s what you want.

I’m not looking specifically for a character event which can handle all, more so a method which allows you to take multiple different events and easily wait for one or the other to be fired. The ‘Current Method’ works, it just takes a considerable amount of time to write for something so simple.

1 Like

Your method as far as I know is pretty much the way to do it, connect all the events, and disconnect when one fires. Just write a function to do it.

local function waitForEvent(...)

	local thread = coroutine.running()
	local signals = {}

	local function resume()
		coroutine.resume(thread)
	end

	for _, event in pairs({...}) do
		table.insert(signals, event:Connect(resume))
	end

	coroutine.yield()

	for _, signal in pairs(signals) do
		signal:Disconnect()
	end

end

waitForEvent(humanoid.Died, player.CharacterAdded)
7 Likes

Surely you can change this from a design perspective - if a character dies they’re going to respawn anyway, so this event implies the other.

1 Like

As I mentioned before, the events could be anything, I just used these as they were the first examples to spring to mind.

@Darkmist101 Thanks for the response! Looks like that’s the best for now unless anyone proposes a better method.

1 Like

Just note that using coroutine.resume will fail silently. If you want to catch errors, wrap it in assert:

assert(coroutine.resume(thread))

There’s nothing wrong with @Darkmist101’s code, but because of what I said above and other weird stacktrace issues when using coroutines, I would personally prefer to create another event to Wait on:

local function WaitForEvent(...)
	local event = Instance.new("BindableEvent")
	local signals = {}
	for _,e in pairs({...}) do
		signals[#signals + 1] = e:Connect(function()
			event:Fire()
		end)
	end
	event:Wait()
	event:Destroy()
	for _,s in pairs(signals) do s:Disconnect() end
end
10 Likes