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() -- 使「事件」發觸發
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 。