BindableEvent 和 BindableFunction 物件讓您能夠將行為綁定在同一側的腳本中 在客戶端-伺服器 邊界 內,並為遊戲行為傳遞特定的期望結果。
可綁定事件最常見的使用案例是對於具有回合制結構的遊戲。例如,您可能有一個「比賽開始」事件,讓其他腳本啟動計時器並顯示排行榜,還有一個對應的「比賽結束」事件,通知其他腳本何時將玩家移回大廳並顯示獲勝者。
因為它們協調腳本之間的活動,可綁定事件通常用於伺服器上,但您也可以在客戶端使用它們。
根據您的遊戲工作方式,可綁定事件可以幫助使您的代碼更模組化,但在需要在腳本之間共享數據的情況下,通常模組腳本是更好的替代方案。您也可以將可綁定事件與模組腳本結合使用,以獲得更清晰的語法,如自定義事件中所述。
可綁定事件
BindableEvent 物件通過腳本之間的非同步單向通信來啟用自定義事件。
當您通過 Fire() 方法觸發 BindableEvent 時,觸發腳本 不 會暫停,目標函數將接收傳遞的參數,但具有某些限制。與所有事件一樣,BindableEvents 會為每個連接的函數創建線程,因此即使其中一個出錯,其他的仍然會繼續執行。
要在 Studio 的 資源管理器 窗口中創建一個新的 BindableEvent:
- 將游標懸停在您希望插入 BindableEvent 的容器上。我們建議使用 ServerScriptService 來進行伺服器腳本之間的通信,使用 ReplicatedStorage 來進行客戶端腳本之間的通信。
- 點擊容器名稱右側出現的 ⊕ 按鈕,然後插入 BindableEvent 實例。
- 將實例重命名為 TestBindableEvent。
在您創建 BindableEvent 後,將一個函數連接到其 Event 事件中,然後從另一個腳本中 Fire() 事件。
事件連接
local ServerScriptService = game:GetService("ServerScriptService")
-- 獲取可綁定事件實例的引用
local bindableEvent = ServerScriptService:WaitForChild("TestBindableEvent")
-- 將匿名函數連接到事件
bindableEvent.Event:Connect(function(data)
print(data) --> 回合開始!
end)
事件觸發local ServerScriptService = game:GetService("ServerScriptService")-- 獲取可綁定事件實例的引用local bindableEvent = ServerScriptService:WaitForChild("TestBindableEvent")-- 觸發可綁定事件bindableEvent:Fire("回合開始!")
自定義回呼
BindableFunction 物件允許腳本之間的同步雙向通信。您可以用它來定義自定義回呼函數,並通過調用 BindableFunction:Invoke() 手動調用它。調用函數的代碼 會暫停 直到找到相應的回呼,回呼將接收您傳遞給 Invoke() 的參數。如果從未設置該回呼,則調用它的腳本不會恢復執行。
要在 Studio 的 資源管理器 窗口中創建一個新的 BindableFunction:
- 將游標懸停在您希望插入 BindableFunction 的容器上。我們建議使用 ServerScriptService 來進行伺服器腳本之間的通信,使用 ReplicatedStorage 來進行客戶端腳本之間的通信。
- 點擊容器名稱右側出現的 ⊕ 按鈕,然後插入 BindableFunction 實例。
- 將實例重命名為 TestBindableFunction。
創建 BindableFunction 後,您可以在一個腳本中連接到其 OnInvoke 回呼,然後從另一個腳本中 Invoke() 回呼函數。
回呼連接
local ServerScriptService = game:GetService("ServerScriptService")
-- 獲取可綁定函數的引用
local bindableFunction = ServerScriptService:WaitForChild("TestBindableFunction")
-- 回呼函數
local function addTwoNumbers(a, b)
return a + b
end
-- 將函數設置為可綁定函數的回呼
bindableFunction.OnInvoke = addTwoNumbers
事件調用local ServerScriptService = game:GetService("ServerScriptService")-- 獲取可綁定函數的引用local bindableFunction = ServerScriptService:WaitForChild("TestBindableFunction")-- 調用回呼函數並輸出返回值local sum = bindableFunction:Invoke(2, 4)print(sum) --> 6
參數限制
當您觸發 BindableEvent 或調用 BindableFunction 時,它會轉發您傳遞的任何參數,這些參數與事件或回呼函數一起傳遞。您可以傳遞任何類型的 Roblox 對象(Enum、Instance 等),還有數字、字符串和布爾值等 Luau 類型,儘管您應該仔細考慮以下限制。
非字符串索引
如果傳遞的表格中任何 索引 不是字符串類型,例如 Instance、userdata 或 function,Roblox 會自動將這些索引轉換為字符串。
事件連接
local ServerScriptService = game:GetService("ServerScriptService")
local bindableEvent = ServerScriptService:WaitForChild("TestBindableEvent")
local function onEventFire(passedTable)
for k, v in passedTable do
print(typeof(k)) --> string
end
end
-- 連接函數到事件
bindableEvent.Event:Connect(onEventFire)
事件觸發local ServerScriptService = game:GetService("ServerScriptService")local bindableEvent = ServerScriptService:WaitForChild("TestBindableEvent")-- 使用包含工作區實例作為鍵的表觸發事件bindableEvent:Fire({[workspace.Baseplate] = true})
表索引
如果您傳遞了一個數據表,請不要傳遞混合的數字和字符串鍵的表。這樣可能會導致傳輸過程中出現元素丟失。相反,請傳遞一個完全由鍵值對(字典)組成的表,或完全由數字索引(數組)組成的表。
事件連接
local ServerScriptService = game:GetService("ServerScriptService")
local bindableEvent = ServerScriptService:WaitForChild("TestBindableEvent")
local function onEventFire(passedTable)
for k, v in passedTable do
print(k .. " = " .. v)
--> 1 = 劍
--> 2 = 弓
--> CharName = Diva Dragonslayer
--> CharClass = Rogue
end
end
-- 連接函數到事件
bindableEvent.Event:Connect(onEventFire)
事件觸發local ServerScriptService = game:GetService("ServerScriptService")local bindableEvent = ServerScriptService:WaitForChild("TestBindableEvent")-- 數字索引表local inventoryData = {"劍", "弓"}-- 字典表local characterData = {CharName = "Diva Dragonslayer",CharClass = "Rogue"}-- 使用一致索引的表觸發事件bindableEvent:Fire(inventoryData)bindableEvent:Fire(characterData)
表身份
傳遞給可綁定事件和回呼的表作為參數被複製,這意味著它們將不會與當前觸發事件或調用回呼時提供的表完全相同。返回給調用者的表也將不會與提供的表完全相同。您可以通過在 BindableFunction 上運行以下腳本來證明這一點,並觀察表的身份是如何不同的。
回呼連接
local ServerScriptService = game:GetService("ServerScriptService")
local bindableFunction = ServerScriptService:WaitForChild("TestBindableFunction")
-- 回呼函數
local function returnTable(passedTable)
-- 在調用時輸出表身份
print(tostring(passedTable)) --> table: 0x48eb7aead27563d9
return passedTable
end
-- 將函數設置為可綁定函數的回呼
bindableFunction.OnInvoke = returnTable
事件調用local ServerScriptService = game:GetService("ServerScriptService")local bindableFunction = ServerScriptService:WaitForChild("TestBindableFunction")local inventoryData = {"劍", "弓"}-- 輸出原始表身份print(tostring(inventoryData)) --> table: 0x059bcdbb2b576549local invokeReturn = bindableFunction:Invoke(inventoryData)-- 輸出返回後的表身份print(tostring(invokeReturn)) --> table: 0x9fcae7919563a0e9
元表
如果一個表具有元表,所有元表信息在傳輸過程中將會丟失。在以下代碼示例中,NumWheels 屬性是 Car 元表的一部分。當伺服器接收以下表時,truck 表具有 Name 屬性,但 不 具有 NumWheels 屬性。
事件連接
local ServerScriptService = game:GetService("ServerScriptService")
local bindableEvent = ServerScriptService:WaitForChild("TestBindableEvent")
local function onEvent(param)
print(param) --> {["Name"] = "MyTruck"}
end
-- 連接函數到事件
bindableEvent.Event:Connect(onEvent)
事件觸發local ServerScriptService = game:GetService("ServerScriptService")local bindableEvent = ServerScriptService:WaitForChild("TestBindableEvent")local Car = {}Car.NumWheels = 4Car.__index = Carlocal truck = {}truck.Name = "MyTruck"setmetatable(truck, Car)-- 使用包含元表的表觸發事件bindableEvent:Fire(truck)