Signal
local Signal = require("@game/ReplicatedStorage/Twill").Signal
local roundEnded = Signal.new<<(winner: Player, score: number) -> ()>>()
roundEnded:Connect(function(winner, score) announce(winner, score)end)
roundEnded:Fire(player, 12)Typed signals
Section titled “Typed signals”The type argument to Signal.new declares what the signal carries. Fire is
checked against it, and listeners are typed without annotation. Luau passes an
explicit type argument between double angle brackets.
local hit = Signal.new<<(target: Model, damage: number) -> ()>>()
hit:Fire(dummy, 25)hit:Fire(dummy) -- refused by the type checkerLeft out, the signal carries anything.
Firing
Section titled “Firing”Listeners run in the order they connected.
Each one runs inside its own xpcall. A listener that raises is reported with
its traceback and stepped over, so the listeners behind it still run.
Two rules govern changes made during a firing, and both match how engine signals behave:
- A listener connected during a firing does not run in that firing. It runs in the next one.
- A listener disconnected during a firing does not run, even if it had not been reached yet.
Firing a signal from inside one of its own listeners runs the new firing there
and then. At 50 levels of that, Fire refuses with an error naming the cause,
rather than running out of stack somewhere less obvious.
Waiting
Section titled “Waiting”Wait parks the calling thread until the signal fires, and hands back what it
was fired with.
A timeout is a number of seconds. When it runs out, Wait returns nothing rather
than staying parked.
Destroy and DisconnectAll wake every parked thread with nothing. A thread
waiting on a signal is never stranded by that signal going away.
Signal.new
Section titled “Signal.new”[Server] | [Client]
Makes a signal with nothing listening to it yet.
function Signal.new<Called>(): Signal<Called>Called is a function type describing what the signal carries.
Signal.wrap
Section titled “Signal.wrap”[Server] | [Client]
Makes a signal that fires whenever an engine signal does, passing on its arguments.
function Signal.wrap<Called>(source: RBXScriptSignal): Signal<Called>Destroying the wrapper disconnects it from the source. Throws when the value is
not an RBXScriptSignal.
Signal.Is
Section titled “Signal.Is”[Server] | [Client]
Answers whether a value is one of these signals.
function Signal.Is(value: any): booleanSignal:Connect
Section titled “Signal:Connect”[Server] | [Client]
Calls a function every time the signal fires, until the connection is let go.
function Signal:Connect(callback: Called): ConnectionThrows on a destroyed signal, and when there is nothing callable to connect.
Signal:Once
Section titled “Signal:Once”[Server] | [Client]
Calls a function on the next firing only, letting the connection go as it runs.
function Signal:Once(callback: Called): ConnectionThrows on a destroyed signal, and when there is nothing callable to connect.
Signal:Wait
Section titled “Signal:Wait”[Server] | [Client]
Parks the calling thread until the signal fires, or until it gives up waiting.
function Signal:Wait(timeout: number?): ...anyReturns
...any - What the signal fired with, or nothing when the wait ran out. Yields.
Throws on a destroyed signal, and when the timeout is not a number.
Signal:Fire
Section titled “Signal:Fire”[Server] | [Client]
Calls every listener in the order they connected.
function Signal:Fire(...: any)Throws on a destroyed signal, and when fired from inside its own listeners 50 levels deep.
Signal:Count
Section titled “Signal:Count”[Server] | [Client]
Returns how many listeners the signal would call were it fired now.
function Signal:Count(): numberUseful in tests: a count that grows across rounds is a leak.
Signal:IsEmpty
Section titled “Signal:IsEmpty”[Server] | [Client]
Answers whether nothing at all is listening.
function Signal:IsEmpty(): booleanSignal:IsDestroyed
Section titled “Signal:IsDestroyed”[Server] | [Client]
Answers whether the signal has been destroyed and can no longer be used.
function Signal:IsDestroyed(): booleanSignal:DisconnectAll
Section titled “Signal:DisconnectAll”[Server] | [Client]
Lets every listener go, and wakes anything waiting with nothing.
function Signal:DisconnectAll()The signal stays usable.
Signal:Destroy
Section titled “Signal:Destroy”[Server] | [Client]
Lets everything go and makes the signal unusable.
function Signal:Destroy()Does nothing the second time.
Connection
Section titled “Connection”| Field | Type | Meaning |
|---|---|---|
Connected | boolean | Whether the signal would still call this listener. |
Signal | Signal | The signal it belongs to. |
Connection:Disconnect
Section titled “Connection:Disconnect”[Server] | [Client]
Lets the listener go, so the signal stops calling it.
function Connection:Disconnect()Does nothing the second time.
Connection:Reconnect
Section titled “Connection:Reconnect”[Server] | [Client]
Takes a let-go listener back on, at the end of the line.
function Connection:Reconnect()Reconnecting puts the listener last, not back where it was. Throws when the signal has been destroyed.
Limits
Section titled “Limits”| Limit | Value |
|---|---|
| Firing from inside its own listeners | 50 levels |