BindableEvent 和 BindableFunction 对象可让你在 同一侧 的 客户端-服务器 边界之间绑定行为,并传达体验中的特定期望结果。
最常见的可绑定事件使用案例是那些具有回合结构的体验。例如,你可能会有一个“匹配开始”事件,其他脚本可以启动计时器并显示排行榜,具有相应的“匹配结束”事件,其他脚本可以知道何时将玩家移回大厅并显示获胜者。
因为它们协调脚本之间的活动,可绑定事件通常在服务器上使用,但您也可以在客户端上使用它们。
根据您的体验如何运行,可绑定的事件可以帮助使您的代码更具模块化,但 模块脚本 经常是在需要在脚本之间共享数据的情况下的更好选择。您还可以使用可绑定的事件与模块脚本结合,以获得更干净的语法,如在 自定义事件 中所述。
可绑定的事件
BindableEvent 对象通过异步、单向通信启用了自定义事件。
当你通过 方法发射一个 时,发射脚本不会产生,目标函数接收传递的参数受到某些限制 。与所有事件一样,BindableEvents 创建每个连接的函数的线程,即使出现一个错误,其他人也会继续。
要使用 Studio 中的 BindableEvent 窗口创建一个新的 :
- 将鼠标悬停在你想要插入 BindableEvent 的容器上。我们建议使用 ServerScriptService 来实现服务器脚本之间的通信,使用 ReplicatedStorage 来实现客户端脚本之间的通信。
- 点击容器名称右侧的 ⊕ 按钮,然后插入 可绑定事件 实例。
- 将实例重命名为 TestBindableEvent 。
在你创建了一个 之后,在一个脚本中连接一个函数到其 事件,然后从另一个脚本中获取事件。
事件连接
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("Round started!")
自定义回调
BindableFunction 对象允许脚本之间的同步、双向通信。您可以使用它来定义自定义回调函数,并通过调用 BindableFunction:Invoke() 手动调用它。调用函数 的代码直到找到相应的回调,并接收你传给 的参数才会产生 。如果回调从未设置,触发它的脚本不会恢复执行。
要使用 Studio 中的 BindableFunction 窗口创建一个新的 :
- 将鼠标悬停在你想要插入 BindableFunction 的容器上。我们建议使用 ServerScriptService 来实现服务器脚本之间的通信,使用 ReplicatedStorage 来实现客户端脚本之间的通信。
- 点击容器名称右侧的 ⊕ 按钮,然后插入 可绑定函数实例 。
- 将实例重命名为 TestBindableFunction 。
一旦你创建了一个 ,你可以在一个脚本中连接到其 回调,然后在另一个脚本中连接回调函数。
回调连接
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 或 函数,Roblox 将自动将这些索引转换为字符串。
事件连接
local ServerScriptService = game:GetService("ServerScriptService")
local bindableEvent = ServerScriptService:WaitForChild("TestBindableEvent")
local function onEventFire(passedTable)
for k, v in passedTable do
print(typeof(k)) --> 字符串
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 = 弓
--> 角色名称 = 迪瓦龙杀手
--> 字符类 = 恶行
end
end
-- 将连接函数连接到事件
bindableEvent.Event:Connect(onEventFire)
事件发射
local ServerScriptService = game:GetService("ServerScriptService")local bindableEvent = ServerScriptService:WaitForChild("TestBindableEvent")-- 数字索引表local inventoryData = {"Sword", "Bow"}-- 词典表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)) --> 表:0x48eb7aead27563d9
return passedTable
end
-- 将函数设置为可绑定的函数的回调
bindableFunction.OnInvoke = returnTable
事件邀请
local ServerScriptService = game:GetService("ServerScriptService")local bindableFunction = ServerScriptService:WaitForChild("TestBindableFunction")local inventoryData = {"Sword", "Bow"}-- 输出原始表身份print(tostring(inventoryData)) --> 表:0x059bcdbb2b576549local invokeReturn = bindableFunction:Invoke(inventoryData)-- 返回传时输出表识别符print(tostring(invokeReturn)) --> table: 0x9fcae7919563a0e9
元表
如果表有一个可转换字段,所有可转换信息在传输中丢失。在以下代码示例中,NumWheels 属性是 Car 可交换的一部分。当服务器收到以下表时,表 具有 属性,但不具有 属性。
事件连接
local ServerScriptService = game:GetService("ServerScriptService")
local bindableEvent = ServerScriptService:WaitForChild("TestBindableEvent")
local function onEvent(param)
print(param) --> {["名称"] = "我的卡车"}
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)