Workspace.SignalBehavior 属性控制是否立即发射或推迟事件处理器。我们推荐使用 Enum.SignalBehavior.Deferred 选项,这有助于提高引擎的性能和正确性。对于 延迟事件 的事件处理器将在下一个恢复点重新启动,以及任何新触发的事件处理器。
下面的图表比较了 Immediate 事件行为和 Deferred 事件行为。
- 使用 Immediate 行为时,如果一个事件触发另一个事件,第二个事件处理器立即发射。
- 使用 Deferred 行为,第二个事件被添加到队列的后面并稍后运行。
总花费时间不会改变,但排序不同。

“重新进入”防止事件在达到某个深度时相继发射,当前限制为 10。
延迟事件优惠
Immediate 行为有一些缺点。每添加到您的游戏的实例、更改的属性或其他触发的触发器,都需要在其他任何事情发生之前运行 Luau 代码。
- 要更改 1,000 个属性,1,000 行代码可能需要在每次更改后运行。
- 奇怪的、难以诊断的错误可能会发生,例如在添加某物之前发射移除事件。
- 性能关键系统可以发射需要它们反复传送给 Luau 的事件。
- 事件处理程序可以随时对地点进行更改或触发其他事件,每次发生事件时。
- 事件可以在重复的情况下触发多次,例如属性两次更改。
通过让 Luau 在引擎生命周期的特定部分运奔跑,引擎可以通过使用一系列假设获得更好的性能:
- 性能敏感的系统不需要让步给 Luau,这会导致性能提升。
- 除非引擎本身发生改变,否则地点在恢复点之外永远不会改变。
恢复点
在被推迟后,事件处理器在下一次恢复点继续恢复。目前,恢复点集包括:
- 输入处理(每次输入处理一次,请参阅 UserInputService)
- 遗产等待脚本重新启动,例如 wait() , spawn() , 和 delay()
常见受影响的代码模式
使用远程事件时,以下示例要么停止正常工作,要么有微妙不同的行为;它们依赖于事件立即恢复。
在执行中触发并捕捉事件中途执行
在这个例子中,false 总是在延迟事件启用时返回,因为回调尚未运奔跑。要正确工作,线程必须等待至少在事件触发时才能放弃。
local success = false
event:Connect(function ()
success = true
end)
doSomethingToTriggerEvent() -- 导致`event`发触发
return success
监听事件的第一次出现
connection = event:Connect(function ()
connection:Disconnect()
-- 做些什么
end)
启用了延迟事件,在您从事件中断之前,多个事件处理器请求可以被队列化。调用 Disconnect() 将丢弃所有待处理的事件处理器请求——与即时事件相同的行为。
或者,使用 Once() 作为更方便的方法来连接到你只需要第一次调用的事件。
改变祖先或属性的事件
延迟事件会导致祖先或属性发生变更后发射的事件:
local part = Instance.new("Part", workspace)
local function onPartDestroying()
print("In signal:", part:GetFullName(), #part:GetChildren())
end
part.Destroying:Connect(onPartDestroying)
part:Destroy()
因为 Destroy() 在调用它的脚本之后立即工作,因此实例已经在 onPartDestroying() 被调用时已被摧毁。了解更多例子,请参阅Instance.Destroying。