延迟的引擎事件

*此内容使用人工智能(Beta)翻译,可能包含错误。若要查看英文页面,请点按 此处

Workspace.SignalBehavior 属性控制是否立即发射或推迟事件处理器。我们推荐使用 Enum.SignalBehavior.Deferred 选项,这有助于提高引擎的性能和正确性。对于 延迟事件 的事件处理器将在下一个恢复点重新启动,以及任何新触发的事件处理器。

下面的图表比较了 Immediate 事件行为和 Deferred 事件行为。

  • 使用 Immediate 行为时,如果一个事件触发另一个事件,第二个事件处理器立即发射。
  • 使用 Deferred 行为,第二个事件被添加到队列的后面并稍后运行。

总花费时间不会改变,但排序不同。

A comparison of three event handlers firing with Immediate and Deferred behavior

“重新进入”防止事件在达到某个深度时相继发射,当前限制为 10。

延迟事件优惠

Immediate 行为有一些缺点。每添加到您的游戏的实例、更改的属性或其他触发的触发器,都需要在其他任何事情发生之前运行 Luau 代码。

  • 要更改 1,000 个属性,1,000 行代码可能需要在每次更改后运行。
  • 奇怪的、难以诊断的错误可能会发生,例如在添加某物之前发射移除事件。
  • 性能关键系统可以发射需要它们反复传送给 Luau 的事件。
  • 事件处理程序可以随时对地点进行更改或触发其他事件,每次发生事件时。
  • 事件可以在重复的情况下触发多次,例如属性两次更改。

通过让 Luau 在引擎生命周期的特定部分运奔跑,引擎可以通过使用一系列假设获得更好的性能:

  • 性能敏感的系统不需要让步给 Luau,这会导致性能提升。
  • 除非引擎本身发生改变,否则地点在恢复点之外永远不会改变。

恢复点

在被推迟后,事件处理器在下一次恢复点继续恢复。目前,恢复点集包括:

常见受影响的代码模式

使用远程事件时,以下示例要么停止正常工作,要么有微妙不同的行为;它们依赖于事件立即恢复。

在执行中触发并捕捉事件中途执行

在这个例子中,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