BindableFunction

Show Deprecated

An object that allows you to give access to functions to external scripts. Functions put in BindableFunctions will not be replicated, therefore making it impossible to use these objects to pass functions between scripts. Functions are invoked through BindableFunction:Invoke(), which calls BindableFunction.OnInvoke.

BindableFunctions do not allow for communication between the server and client. If you are looking for this functionality use RemoteFunctions.

BindableEvents vs BindableFunctions

Unlike BindableFunctions, BindableEvents only allow for one-way communication between two scripts:

  • When a script invokes a BindableFunction it yields until the event is handled and returned by the subscribed script synchronously. This allows for scripts to effectively pass data during and after an event.
  • When a script fires a BindableEvent, however, it does not yield for a return. The script continues executing as the event is handled by the subscribed script asynchronously.

BindableFunctions vs RemoteFunctions

While BindableFunctions allow for two-way communication server-server scripts or client-client LocalScripts, RemoteFunctions allow for two-way communicate the server and client. For more information on RemoteFunctions, see Remote Events and Functions.

Limitations

Invocations will yield until the corresponding callback is found. If the callback was never set, the script that invokes it will not resume execution.

Subscription

Only one function can be bound to BindableFunction:Invoke() at a time. If you assign multiple functions, only the last one assigned will be used.

Parameter Limitations

Any type of Roblox object such as an Enum, Instance, or userdata can be passed as a parameter when a RemoteEvent is fired or a RemoteFunction invoked. Lua types such as numbers, strings, and booleans can also be passed, although there are some limitations on how data can be passed.

Table Identity

Copies of tables are produced when passed as arguments to or returned from the OnInvoke callback. This means that means that tables passed as arguments will not be exactly equivalent to those provided on invocation, and tables returned to the invoker will not be exactly equivalent to the ones returned by the OnInvoke callback. You can demonstrate this by running the following script in a BindableFunction:


1local bindableFunction = script.Parent
2
3bindableFunction.OnInvoke = function (t)
4 print("OnInvoke", tostring(t), t)
5 t = {bar = "foo"}
6 print("OnInvoke2", tostring(t), t)
7 return t
8end
9
10local t = {foo = "bar"}
11print("Subscriber", tostring(t), t)
12local retVal = script.Parent:Invoke(t)
13print("return", tostring(retVal), retVal)
14

The above code may produce the following results in the output. Notice how the memory addresses of every table printed are completely different from each other, indicating they each represent different tables:


1 13:55:22.228 Subscriber table: 0xc7daaba4d5307f10 ▶ {...} - Publisher:11
2 13:55:22.229 OnInvoke table: 0x2ee92a7818e7d210 ▶ {...} - Publisher:4
3 13:55:22.229 OnInvoke2 table: 0xfa4ee529ddadf290 ▶ {...} - Publisher:6
4 13:55:22.229 return table: 0x35b7bc1bc323d510 ▶ {...} - Publisher:13
5

Mixed Tables

Avoid passing a mixed table (some values indexed by number and others by key), as only the data indexed by number will be passed. For example, when the server receives the colorData table illustrated below, it only sees indices 1 and 2 containing "Blue" and "Yellow" while the other data is lost in the transfer. Note, however, that sub-tables do not need to be indexed in the same way as their parent — in other words, as long as each individual sub-table is indexed with the same type, all of the data is preserved.

Metatables are not preserved.

Non-String Indices

If any indices of a passed table are non-string type (Instance, userdata, function, another table, etc.), those indices will be converted to a string.


1-- Mixed table
2local colorData = {}
3colorData[1] = "Blue"
4colorData[2] = "Yellow"
5colorData["Color1"] = "Green"
6colorData["Color2"] = "Red"
7
8-- Table with two key-indexed sub-tables
9local playerData = {}
10playerData["CharData"] = {
11 -- All children indexed by key
12 CharName = "Diva Dragonslayer",
13 CharClass = "Knight"
14}
15playerData["Inventory"] = {
16 -- All children numerically indexed
17 "Sword",
18 "Bow",
19 "Rope"
20}
21

Functions

Functions passed as parameters will not be replicated, therefore making it impossible to use these objects to pass functions between scripts.

Code Samples

BindableFunction Addition

1local bindableFunction = script.Parent
2
3-- Define a function for use with the BindableFunction
4local function AddTwoNumbers(a, b)
5 return a + b
6end
7
8-- Set the OnInvoke callback to be our function
9bindableFunction.OnInvoke = AddTwoNumbers
10
11-- Invoke the BindableFunction
12print(bindableFunction:Invoke(25, 44))
BindableFunction Valid Values

1local bindableFunction = script.Parent
2
3-- Dummy function
4bindableFunction.OnInvoke = function(...)
5 return ...
6end
7
8-- These values CAN be sent to/from BindableFunctions
9bindableFunction:Invoke() -- nil
10bindableFunction:Invoke(25) -- numbers
11bindableFunction:Invoke("hello") -- strings
12bindableFunction:Invoke(true) -- booleans
13bindableFunction:Invoke("buy", 25) -- multiple values are OK
14bindableFunction:Invoke({ 1, 2, 3 }) -- tables as arrays with no gaps
15-- note the curly braces
16bindableFunction:Invoke({ -- tables with string keys only
17 hello = "world",
18 goodbye = "world",
19})
20bindableFunction:Invoke({ -- tables with string keys
21 point = { 1, 2 }, -- whose values are also valid
22 point2 = { 3, 4 },
23})
24bindableFunction:Invoke({ -- tables as arrays
25 { 1, 2, 3 }, -- whose values also are valid
26 { hello = "world" },
27})
28
29-- These are some values you CANNOT send to/from BindableFunctions
30bindableFunction:Invoke({ 1, nil, 3 }) -- tables as arrays cannot have nil gaps
31bindableFunction:Invoke({
32 [{}] = "hello", -- table keys can only be numbers OR strings
33})
34bindableFunction:Invoke({ -- tables keys cannot be BOTH numbers AND strings
35 [1] = "apple",
36 hello = "world",
37})

Summary

Properties

Events

Methods

Invoke(arguments: Tuple): Tuple  YIELDS

Calls the BindableFunction.OnInvoke callback of the BindableFunction, returning any values returned by the callback.

Callbacks

OnInvoke(arguments: Tuple)  

Properties

Events

Methods

Invoke

Yields

Calls the BindableFunction.OnInvoke callback and returns any values that were returned by the callback.

Limitations

Invocations will yield until the corresponding callback is found. If the callback was never set, the script that invokes it will not resume execution.

Subscription

Only one function can be bound to BindableFunction:Invoke() at a time. If you assign multiple functions, only the last one assigned will be used.

Parameter Limitations

Any type of Roblox object such as an Enum, Instance, or userdata can be passed as a parameter when a RemoteEvent is fired or a RemoteFunction invoked. Lua types such as numbers, strings, and booleans can also be passed, although there are some limitations on how data can be passed.

Table Identity

Copies of tables are produced when passed as arguments to or returned from the OnInvoke callback. This means that means that tables passed as arguments will not be exactly equivalent to those provided on invocation, and tables returned to the invoker will not be exactly equivalent to the ones returned by the OnInvoke callback. You can demonstrate this by running the following script in a BindableFunction:


1local bindableFunction = script.Parent
2
3bindableFunction.OnInvoke = function (t)
4 print("OnInvoke", tostring(t), t)
5 t = {bar = "foo"}
6 print("OnInvoke2", tostring(t), t)
7 return t
8end
9
10local t = {foo = "bar"}
11print("Subscriber", tostring(t), t)
12local retVal = script.Parent:Invoke(t)
13print("return", tostring(retVal), retVal)
14

The above code may produce the following results in the output. Notice how the memory addresses of every table printed are completely different from each other, indicating they each represent different tables:


1 13:55:22.228 Subscriber table: 0xc7daaba4d5307f10 ▶ {...} - Publisher:11
2 13:55:22.229 OnInvoke table: 0x2ee92a7818e7d210 ▶ {...} - Publisher:4
3 13:55:22.229 OnInvoke2 table: 0xfa4ee529ddadf290 ▶ {...} - Publisher:6
4 13:55:22.229 return table: 0x35b7bc1bc323d510 ▶ {...} - Publisher:13
5

Mixed Tables

Avoid passing a mixed table (some values indexed by number and others by key), as only the data indexed by number will be passed. For example, when the server receives the colorData table illustrated below, it only sees indices 1 and 2 containing "Blue" and "Yellow" while the other data is lost in the transfer. Note, however, that sub-tables do not need to be indexed in the same way as their parent — in other words, as long as each individual sub-table is indexed with the same type, all of the data is preserved.

Metatables are not preserved.

Non-String Indices

If any indices of a passed table are non-string type (Instance, userdata, function, another table, etc.), those indices will be converted to a string.


1-- Mixed table
2local colorData = {}
3colorData[1] = "Blue"
4colorData[2] = "Yellow"
5colorData["Color1"] = "Green"
6colorData["Color2"] = "Red"
7
8-- Table with two key-indexed sub-tables
9local playerData = {}
10playerData["CharData"] = {
11 -- All children indexed by key
12 CharName = "Diva Dragonslayer",
13 CharClass = "Knight"
14}
15playerData["Inventory"] = {
16 -- All children numerically indexed
17 "Sword",
18 "Bow",
19 "Rope"
20}
21

Functions

Functions passed as parameters will not be replicated, therefore making it impossible to use these objects to pass functions between scripts.

Parameters

arguments: Tuple

Values to be passed to the callback.


Returns

Values passed to the callback.

Code Samples

BindableFunction Addition

1local bindableFunction = script.Parent
2
3-- Define a function for use with the BindableFunction
4local function AddTwoNumbers(a, b)
5 return a + b
6end
7
8-- Set the OnInvoke callback to be our function
9bindableFunction.OnInvoke = AddTwoNumbers
10
11-- Invoke the BindableFunction
12print(bindableFunction:Invoke(25, 44))
BindableFunction Valid Values

1local bindableFunction = script.Parent
2
3-- Dummy function
4bindableFunction.OnInvoke = function(...)
5 return ...
6end
7
8-- These values CAN be sent to/from BindableFunctions
9bindableFunction:Invoke() -- nil
10bindableFunction:Invoke(25) -- numbers
11bindableFunction:Invoke("hello") -- strings
12bindableFunction:Invoke(true) -- booleans
13bindableFunction:Invoke("buy", 25) -- multiple values are OK
14bindableFunction:Invoke({ 1, 2, 3 }) -- tables as arrays with no gaps
15-- note the curly braces
16bindableFunction:Invoke({ -- tables with string keys only
17 hello = "world",
18 goodbye = "world",
19})
20bindableFunction:Invoke({ -- tables with string keys
21 point = { 1, 2 }, -- whose values are also valid
22 point2 = { 3, 4 },
23})
24bindableFunction:Invoke({ -- tables as arrays
25 { 1, 2, 3 }, -- whose values also are valid
26 { hello = "world" },
27})
28
29-- These are some values you CANNOT send to/from BindableFunctions
30bindableFunction:Invoke({ 1, nil, 3 }) -- tables as arrays cannot have nil gaps
31bindableFunction:Invoke({
32 [{}] = "hello", -- table keys can only be numbers OR strings
33})
34bindableFunction:Invoke({ -- tables keys cannot be BOTH numbers AND strings
35 [1] = "apple",
36 hello = "world",
37})

Callbacks

OnInvoke

Parameters

arguments: Tuple

Returns

Code Samples

Temporary DataStore

1local Players = game:GetService("Players")
2local ServerStorage = game:GetService("ServerStorage")
3
4-- TempDataStore (Script 1)
5local GetData = Instance.new("BindableFunction")
6GetData.Name = "GetData"
7GetData.Parent = ServerStorage
8
9local SetData = Instance.new("BindableFunction")
10SetData.Name = "SetData"
11SetData.Parent = ServerStorage
12
13local PlayerData = {}
14
15local function getData(player)
16 return PlayerData[player.UserId]
17end
18
19local function setData(player, value)
20 PlayerData[player.UserId] = value
21 return PlayerData[player.UserId]
22end
23
24local function addPlayerData(player)
25 table.insert(PlayerData, player.UserId, 0)
26end
27
28local function removePlayerData(player)
29 table.remove(PlayerData, player.UserId)
30end
31
32GetData.OnInvoke = getData
33SetData.OnInvoke = setData
34
35Players.PlayerAdded:Connect(addPlayerData)
36Players.PlayerRemoving:Connect(removePlayerData)
37
38-- ActivateButton (Script 2)
39local ClickDetector = Instance.new("ClickDetector")
40ClickDetector.Parent = script.Parent
41
42local function getDataClickDetector(player)
43 print(player.Name .. "'s Current Balance: " .. GetData:Invoke(player))
44end
45
46local function setDataClickDetector(player, value)
47 value = value or 100
48 print("Set " .. player.Name .. "'s Balance to: " .. SetData:Invoke(value))
49end
50
51local function incrementDataClickDetector(player)
52 local balance = GetData:Invoke(player)
53 print("Set " .. player.Name .. "'s Balance to: " .. SetData:Invoke(player, balance + 1))
54end
55
56ClickDetector.MouseClick:Connect(incrementDataClickDetector)
57ClickDetector.RightMouseClick:Connect(setDataClickDetector)
58ClickDetector.MouseHoverEnter:Connect(getDataClickDetector)
BindableFunction Addition

1local bindableFunction = script.Parent
2
3-- Define a function for use with the BindableFunction
4local function AddTwoNumbers(a, b)
5 return a + b
6end
7
8-- Set the OnInvoke callback to be our function
9bindableFunction.OnInvoke = AddTwoNumbers
10
11-- Invoke the BindableFunction
12print(bindableFunction:Invoke(25, 44))
BindableFunction Valid Values

1local bindableFunction = script.Parent
2
3-- Dummy function
4bindableFunction.OnInvoke = function(...)
5 return ...
6end
7
8-- These values CAN be sent to/from BindableFunctions
9bindableFunction:Invoke() -- nil
10bindableFunction:Invoke(25) -- numbers
11bindableFunction:Invoke("hello") -- strings
12bindableFunction:Invoke(true) -- booleans
13bindableFunction:Invoke("buy", 25) -- multiple values are OK
14bindableFunction:Invoke({ 1, 2, 3 }) -- tables as arrays with no gaps
15-- note the curly braces
16bindableFunction:Invoke({ -- tables with string keys only
17 hello = "world",
18 goodbye = "world",
19})
20bindableFunction:Invoke({ -- tables with string keys
21 point = { 1, 2 }, -- whose values are also valid
22 point2 = { 3, 4 },
23})
24bindableFunction:Invoke({ -- tables as arrays
25 { 1, 2, 3 }, -- whose values also are valid
26 { hello = "world" },
27})
28
29-- These are some values you CANNOT send to/from BindableFunctions
30bindableFunction:Invoke({ 1, nil, 3 }) -- tables as arrays cannot have nil gaps
31bindableFunction:Invoke({
32 [{}] = "hello", -- table keys can only be numbers OR strings
33})
34bindableFunction:Invoke({ -- tables keys cannot be BOTH numbers AND strings
35 [1] = "apple",
36 hello = "world",
37})