Remote Events and Functions

All experiences require communication between the server and the players' clients. For example when a player presses W to move forward, the keyboard input is received on the player's client. The client then communicates this to the server, which responds by moving the position of the player's character forward. RemoteEvent and RemoteFunction objects allow you to create your own events and functions to communicate your own behavior between the client-server boundary.

RemoteEvents allow for asynchronous, one-way communication across the boundary, while RemoteFunctions allow for synchronous, two-way communication (sending a request across the boundary and yielding until a response is received from the recipient).

Usage Reference

The following tables serve as a quick reference for how to use remote events and functions to communicate between the client and server.

Client → Server
Client RemoteEvent:FireServer(args)
Server RemoteEvent.OnServerEvent:Connect(function(player, args))
Server → Client
Server RemoteEvent:FireClient(player, args)
Client RemoteEvent.OnClientEvent:Connect(function(args))
Server → All Clients
Server RemoteEvent:FireAllClients(args)
Client RemoteEvent.OnClientEvent:Connect(function(args))

Remote Events

A RemoteEvent object allows asynchronous, one-way communication across the client-server boundary. You can use it to send requests across the boundary without yielding for a response.

Creating Remote Events

Create RemoteEvent objects in a location that both the client and server can access, such as ReplicatedStorage.

  1. In the Explorer window, hover over ReplicatedStorage and click the button.

  2. Click RemoteEvent from the contextual menu.

  3. Rename the new RemoteEvent to describe its purpose.

Using Remote Events

You can use RemoteEvents to facilitate one-way communication from one client to the server, the server to one client, or the server to all clients.

Client to Server

You can use a LocalScript to trigger an event on the server by calling the FireServer() method on a RemoteEvent. If you pass arguments to FireServer(), they pass to the event handler on the server. The first parameter of the event handler is always the Player object of the client that calls it, and additional parameters follow.

Client RemoteEvent:FireServer(args)
Server RemoteEvent.OnServerEvent:Connect(function(player, args))

The following LocalScript and Script fire and respond to a RemoteEvent instance in ReplicatedStorage named RemoteEventTest. The LocalScript calls FireServer() on the RemoteEvent instance. In response, the Script connects an event handler to OnServerEvent that creates a new Part on the server.

LocalScript in StarterPlayerScripts

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local remoteEvent = ReplicatedStorage:WaitForChild("RemoteEventTest")
-- Fire the RemoteEvent and pass additional arguments
remoteEvent:FireServer(BrickColor.Red(), Vector3.new(0, 25, 0))
Script in ServerScriptService

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local remoteEvent = ReplicatedStorage:WaitForChild("RemoteEventTest")
local function onCreatePart(player, partColor, partPosition)
print(player.Name .. " fired the RemoteEvent")
local newPart = Instance.new("Part")
newPart.BrickColor = partColor
newPart.Position = partPosition
newPart.Parent = workspace
end
remoteEvent.OnServerEvent:Connect(onCreatePart)

Server to Client

You can use a Script to trigger an event on a client by calling the FireClient() method on a RemoteEvent. The first argument of the FireClient() is the Player object of the client that you want to respond to the event, and additional arguments pass to the client.

Server RemoteEvent:FireClient(player, args)
Client RemoteEvent.OnClientEvent:Connect(function(args))

The following Script and LocalScript fire and respond to a RemoteEvent instance in ReplicatedStorage named RemoteEventTest. The Script calls FireClient() on the RemoteEvent to fire it. The LocalScript connects an event handler to the OnClientEvent event. The event handler doesn't need to list the Player object as its first argument because you can determine the player on the client with Players.LocalPlayer.

Script in ServerScriptService

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")
local remoteEvent = ReplicatedStorage:WaitForChild("RemoteEventTest")
local function onPlayerAdded(player)
print("[Server] Firing event to player", player.Name)
remoteEvent:FireClient(player, Players.MaxPlayers, Players.RespawnTime)
end
Players.PlayerAdded:Connect(onPlayerAdded)
LocalScript in StarterPlayerScripts

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")
local remoteEvent = ReplicatedStorage:WaitForChild("RemoteEventTest")
local player = Players.LocalPlayer
local function onNotifyPlayer(maxPlayers, respawnTime)
print("[Client] Event received by player", player.Name)
print(maxPlayers, respawnTime)
end
remoteEvent.OnClientEvent:Connect(onNotifyPlayer)

Server to All Clients

You can use a Script to trigger an event on all clients by calling the FireAllClients() method on a RemoteEvent. Unlike FireClient(), the FireAllClients() method doesn't require a Player object because it fires the RemoteEvent to all clients.

Server RemoteEvent:FireAllClients(args)
Client RemoteEvent.OnClientEvent:Connect(function(args))

The following Script and LocalScript fire and respond to a RemoteEvent instance in ReplicatedStorage named RemoteEventTest. The Script calls FireAllClients() on the RemoteEvent to fire it. The LocalScript connects an event handler to the OnClientEvent event that prints to the Output window.

Script in ServerScriptService

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local remoteEvent = ReplicatedStorage:WaitForChild("RemoteEventTest")
local secondsRemaining = 5
-- Fire the RemoteEvent every second until time expires
for t = secondsRemaining, 1, -1 do
remoteEvent:FireAllClients(t)
task.wait(1)
end
LocalScript in StarterPlayerScripts

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local remoteEvent = ReplicatedStorage:WaitForChild("RemoteEventTest")
local function onTimerUpdate(seconds)
print(seconds)
end
-- Call "onTimerUpdate()" when the server fires the RemoteEvent
remoteEvent.OnClientEvent:Connect(onTimerUpdate)

Client to Client

Clients cannot communicate directly with other clients, although you can effectively dispatch an event from one client to another by using the FireServer() method, then calling FireClient() or FireAllClients() in the event handler for OnServerEvent.

Remote Functions

A RemoteFunction object allows synchronous, two-way communication across the client-server boundary. The sender of a remote function will wait to receive a response from the recipient.

Creating Remote Functions

Create RemoteFunction objects in a location that both the client and server can access, such as ReplicatedStorage.

  1. In the Explorer window, hover over ReplicatedStorage and click the button.

  2. Click RemoteFunction from the contextual menu.

  3. Rename the new RemoteFunction to describe its purpose.

Using Remote Functions

You can use RemoteFunction objects to facilitate two-way communication between one client and the server or the server and one client.

Client to Server to Client

You can use a Script to call a function on the server by calling the InvokeServer() method on a RemoteFunction. The LocalScript that invokes the RemoteFunction yields until the callback of the RemoteFunction returns. Arguments that you pass to InvokeServer() pass to the OnServerInvoke callback of the RemoteFunction. If you define multiple callbacks to the same RemoteFunction, the last definition executes.

Client RemoteFunction:InvokeServer(args)
Server RemoteFunction.OnServerInvoke = function(player, args)

The following LocalScript and Script have two-way communication using a RemoteFunction instance in ReplicatedStorage named RemoteFunctionTest. The LocalScript calls InvokeServer() on the RemoteFunction instance with extra arguments. In response, the Script defines the callback of the RemoteFunction and calls it using the Player of the client and the extra arguments. The Script then returns the return value of the callback to the LocalScript.

LocalScript in StarterPlayerScripts

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local remoteFunction = ReplicatedStorage:WaitForChild("RemoteFunctionTest")
-- Invoke the Function
-- Pass a brick color and position when invoking the function
local newPart = remoteFunction:InvokeServer(BrickColor.Red(), Vector3.new(0, 25, 0))
print("The server created the requested part:", newPart)
Script in ServerScriptService

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local remoteFunction = ReplicatedStorage:WaitForChild("RemoteFunctionTest")
-- Script in ServerScriptService to create Part with the passed properties
local function createPart(player, partColor, partPosition)
print(player.Name .. " requested a new part")
local newPart = Instance.new("Part")
-- Use partColor and partPosition to set the Part's BrickColor and Position
newPart.BrickColor = partColor
newPart.Position = partPosition
newPart.Parent = workspace
return newPart
end
-- Bind createPart() to the `Class.RemoteFunction`'s OnServerInvoke callback
remoteFunction.OnServerInvoke = createPart

Server to Client to Server

You can use a Script to call a function on the client by calling the InvokeClient() method on a RemoteFunction, but it has the following serious risks:

For actions that don't require two-way communications, such as updating a GUI, use a RemoteEvent and communicate from the server to client.

Parameter Limitations

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