For the complete documentation index, see llms.txt. This page is also available as Markdown.

Communication Within the Same Environment

Overview

Use BindableEvent or BindableFunction to communicate between scripts that live in the same environment, such as between servers or between clients.

Use BindableEvent when you only need to send a notification and move on, and BindableFunction when you need the result of the work sent back to you.

Neither object can cross the client-server boundary. For communication that crosses it, use RemoteEvent or RemoteFunction.

BindableEvent and BindableFunction Objects

BindableEvent is an object provided to handle events within the same environment, supporting one-way communication. The sending script keeps running without stopping.

BindableFunction is an object provided to handle requests and responses within the same environment, supporting two-way communication. The calling script yields until the assigned callback returns a value.

Item
BindableEvent
BindableFunction

Direction

One-way (notification)

Two-way (request and response)

Sender behavior

Keeps running without stopping

Waits until a value is returned

How to connect

Event:Connect(function) — many can be connected

OnInvoke = function — only one can be assigned

Return value

Cannot receive one

Receives multiple values as a Tuple

Error on the receiving side

Does not affect other connected functions

Propagates to the caller

Use BindableEvent for notifications that need no result. A synchronous call stops the caller, so a long-running task also delays the rest of the game flow.

💡 Tip. To clearly distinguish whether the communication is between Server to Server or Client to Client, it is recommended to use prefixes such as S2S_ or C2C_ in the name. This makes the object’s role intuitive and improves code readability and maintainability.

Implementing Communication with BindableEvent

When firing an event with BindableEvent, you can send arguments along with it. These arguments are passed when calling the Fire method and can be received by the callback function on the receiving side.

Server ➡ Server

In Script1

In Script2

Client ➡ Client

In LocalScript1

In LocalScript2

Implementing Communication with BindableFunction

The handling script assigns a callback to OnInvoke, and the calling script calls it with the Invoke method. Arguments passed to Invoke arrive at the callback as-is, and whatever the callback returns goes back to the caller.

Server ➡ Server

In Script1 (handling side)

In Script2 (calling side)

Client ➡ Client

In LocalScript1 (handling side)

In LocalScript2 (calling side)

Callback Rules for OnInvoke

OnInvoke is not an event but a property that holds a function. It works differently from Event, so keep these three points in mind.

  • You cannot use :Connect(). Assign it as OnInvoke = function.

  • Only one function is kept. If you assign more than once, only the last assigned function runs.

  • If you omit return, the caller receives nil. Using that value directly can cause an error later in the code.

Overlapping calls each run the callback separately. If you replace OnInvoke while a call is in progress, that call finishes with the previous function, and only new calls made afterward use the new one.

Important Notes

The Call Never Resumes Without a Callback

If you call a BindableFunction whose OnInvoke has not been assigned, the calling thread stops forever with no error and no timeout. There is no way to cancel the wait.

  • Design your initialization order so the callback is assigned before any call is made.

  • If the work can take a long time, consider sending the request with a BindableEvent and reporting the result through a separate event when it finishes.

You can tell a hang and an error apart by the symptom. Assigning a value that is not a function (a module table, for example) to OnInvoke passes silently, and the error appears the moment you call it. In other words, if nothing happens at all, the callback is not assigned; if an error appears right at the call, a non-function value was assigned.

BindableEvent has no such hang. Even with no connected function, the script that called Fire keeps running.

Callback Errors Propagate to the Caller

An error raised in a BindableFunction callback is delivered to the caller and interrupts the calling code. If the work can fail, wrap the call in pcall() or return a success flag instead of raising an error.

BindableEvent runs each connected function on its own thread, so an error in one of them affects neither the others nor the sender.

Table Arguments Are Copies

Both objects copy the table you pass before handing it to the receiving side. Filling an argument table on the receiving side leaves the sender’s original empty, so you must receive what you need as a return value. Metatables are not delivered, so you cannot pass an object with methods as-is.

When passing a table, use string keys only. If a table holds both array elements and named fields, the named fields disappear, and instances or functions used as keys turn into strings that can no longer be looked up with the original key. No error or warning is raised during this process.

Advanced Usage

  • For communication that needs no return value, use BindableEvent so the caller does not stop.

  • If you only need to share values or functions, a ModuleScript is simpler and faster. Use the Bindable objects when you need to keep scripts loosely coupled.

  • Do not perform long waits inside a callback (task.wait, external communication, and so on). The caller waits just as long.

  • When using a single object to handle several kinds of requests, add a first argument that indicates the request type.

  • Clients of different players cannot communicate through these objects. In that case, use RemoteEvent or RemoteFunction, which go through the server.

Last updated