Eventos remotos e callbacks

*Este conteúdo é traduzido por IA (Beta) e pode conter erros. Para ver a página em inglês, clique aqui.

Os jogos Roblox são multijogador por padrão, portanto, todos os jogos se comunicam inerentemente entre o servidor e os clientes conectados dos jogadores. No caso mais simples, à medida que os jogadores movem seus personagens, certas propriedades Humanoid, como estados, são comunicadas ao servidor, que passa essas informações para outros clientes conectados.

Eventos remotos e callbacks permitem que você se comunique através da fronteira cliente-servidor:

  • RemoteEvents habilitam comunicação unidirecional (enviando um pedido e não esperando por uma resposta).
  • UnreliableRemoteEvents habilitam comunicação unidirecional para dados que mudam continuamente ou não são críticos para o estado do jogo. Esses eventos trocam a ordenação e a confiabilidade por um desempenho de rede melhorado.
  • RemoteFunctions habilitam comunicação bidirecional (enviando um pedido e esperando até que uma resposta seja recebida do destinatário).

Ao contrário dos eventos vinculáveis, que têm utilidade mais limitada, os casos de uso para eventos remotos e funções são numerosos demais para listar:

  • Jogabilidade - A jogabilidade básica, como um jogador alcançando o final de um nível, pode requerer um evento remoto. Um script de cliente notifica o servidor e scripts do servidor redefinem a posição do jogador.
  • Verificação no servidor - Se um jogador tenta beber uma poção, ele realmente tem essa poção? Para garantir a justiça, o servidor deve ser a fonte da verdade para um jogo. Um script de cliente pode usar um evento remoto para notificar o servidor de que o jogador está bebendo uma poção, e então scripts do servidor podem decidir se o jogador realmente tem essa poção e se deve conceder algum benefício.
  • Atualizações da interface do usuário - À medida que o estado do jogo muda, scripts do servidor podem usar eventos remotos para notificar os clientes sobre mudanças de pontuações, objetivos, etc.
  • Compras no Mercado do jogo - Para uma implementação de exemplo que usa funções remotas, veja Compras de assinatura com prompts.

Referência rápida

As seguintes tabelas servem como uma referência rápida sobre como usar RemoteEvents e RemoteFunctions para comunicar entre o cliente e o servidor.

Cliente → Servidor
ClienteRemoteEvent:FireServer(args)
ServidorRemoteEvent.OnServerEvent:Connect(function(player, args))
Servidor → Cliente
ServidorRemoteEvent:FireClient(player, args)
ClienteRemoteEvent.OnClientEvent:Connect(function(args))
Servidor → Todos os Clientes
ServidorRemoteEvent:FireAllClients(args)
ClienteRemoteEvent.OnClientEvent:Connect(function(args))

Eventos remotos

Um objeto RemoteEvent facilita comunicação assíncrona, unidirecional através da fronteira cliente-servidor sem esperar por uma resposta.

Para criar um novo RemoteEvent através da janela Explorer no Studio:

  1. Passe o mouse sobre o contêiner em que você deseja inserir o RemoteEvent. Para garantir que tanto o servidor quanto o cliente tenham acesso, ele deve estar em um lugar onde ambos os lados possam vê-lo, como ReplicatedStorage, embora em alguns casos seja apropriado armazená-lo em Workspace ou dentro de um Tool.
  2. Clique no botão que aparece à direita do nome do contêiner e insira uma instância de RemoteEvent.
  3. Renomeie a instância para descrever seu propósito.

Uma vez que você criou um RemoteEvent, ele pode facilitar a comunicação unidirecional do cliente para o servidor, do servidor para o cliente ou do servidor para todos os clientes.

Cliente → Servidor
Servidor → Cliente
Servidor → Todos os Clientes

Cliente → servidor

Você pode usar um LocalScript para disparar um evento no servidor chamando o método FireServer() em um RemoteEvent. Se você passar argumentos para FireServer(), eles serão passados para o manipulador de eventos no servidor com certas limitações. Note que o primeiro parâmetro do manipulador de eventos no servidor é sempre o objeto Player do cliente que o chama, e parâmetros adicionais o seguem.

ClienteRemoteEvent:FireServer(args)
ServidorRemoteEvent.OnServerEvent:Connect(function(player, args))

O seguinte Script conecta um manipulador de eventos ao OnServerEvent que cria um novo Part no servidor. O LocalScript correspondente então chama FireServer() na instância de RemoteEvent com a Color e Position desejadas para a peça.

Conexão de Evento - Script

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Workspace = game:GetService("Workspace")
-- Obter referência à instância do evento remoto
local remoteEvent = ReplicatedStorage:FindFirstChildOfClass("RemoteEvent")
local function onCreatePart(player, partColor, partPosition)
print(player.Name .. " disparou o RemoteEvent")
local newPart = Instance.new("Part")
newPart.Color = partColor
newPart.Position = partPosition
newPart.Parent = Workspace
end
-- Conectar função ao evento
remoteEvent.OnServerEvent:Connect(onCreatePart)
Disparo de Evento - LocalScript

local ReplicatedStorage = game:GetService("ReplicatedStorage")
-- Obter referência à instância do evento remoto
local remoteEvent = ReplicatedStorage:FindFirstChildOfClass("RemoteEvent")
-- Dispara o evento remoto e passa argumentos adicionais
remoteEvent:FireServer(Color3.fromRGB(255, 0, 0), Vector3.new(0, 25, -20))

Servidor → cliente

Você pode usar um Script para disparar um evento em um cliente chamando o método FireClient() em um RemoteEvent. O primeiro argumento para FireClient() é o objeto Player do cliente que você deseja que responda ao evento, e argumentos adicionais são passados para o cliente com certas limitações. Note que o manipulador de eventos não precisa incluir o objeto Player como seu primeiro argumento porque você pode determinar o jogador no cliente com Players.LocalPlayer.

ServidorRemoteEvent:FireClient(player, args)
ClienteRemoteEvent.OnClientEvent:Connect(function(args))

O seguinte LocalScript conecta um manipulador de eventos ao evento OnClientEvent. O Script correspondente então escuta por jogadores que entram no servidor e chama FireClient() para cada um com dados arbitrários.

Conexão de Evento - LocalScript

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")
-- Obter referência à instância do evento remoto
local remoteEvent = ReplicatedStorage:FindFirstChildOfClass("RemoteEvent")
local player = Players.LocalPlayer
local function onNotifyPlayer(maxPlayers, respawnTime)
print("[Cliente] Evento recebido pelo jogador", player.Name)
print(maxPlayers, respawnTime)
end
-- Conectar função ao evento
remoteEvent.OnClientEvent:Connect(onNotifyPlayer)
Disparo de Evento - Script

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")
-- Obter referência à instância do evento remoto
local remoteEvent = ReplicatedStorage:FindFirstChildOfClass("RemoteEvent")
-- Ouvir jogadores que entram e despachar evento remoto para cada um
local function onPlayerAdded(player)
print("[Servidor] Disparando evento para o jogador", player.Name)
remoteEvent:FireClient(player, Players.MaxPlayers, Players.RespawnTime)
end
Players.PlayerAdded:Connect(onPlayerAdded)

Servidor → todos os clientes

Você pode usar um Script para disparar um evento em todos os clientes chamando o método FireAllClients() em um RemoteEvent. Ao contrário de FireClient(), o método FireAllClients() não requer um objeto Player porque dispara o RemoteEvent para todos os clientes.

ServidorRemoteEvent:FireAllClients(args)
ClienteRemoteEvent.OnClientEvent:Connect(function(args))

O seguinte LocalScript conecta um manipulador de eventos ao evento OnClientEvent, que exibe um tempo de contagem regressiva restante. O Script correspondente então chama FireAllClients() em um loop a cada segundo para disparar o RemoteEvent para todos os clientes.

Conexão de Evento - LocalScript

local ReplicatedStorage = game:GetService("ReplicatedStorage")
-- Obter referência à instância do evento remoto
local remoteEvent = ReplicatedStorage:FindFirstChildOfClass("RemoteEvent")
local function onTimerUpdate(seconds)
print(seconds)
end
-- Conectar função ao evento
remoteEvent.OnClientEvent:Connect(onTimerUpdate)
Disparo de Evento - Script

local ReplicatedStorage = game:GetService("ReplicatedStorage")
-- Obter referência à instância do evento remoto
local remoteEvent = ReplicatedStorage:FindFirstChildOfClass("RemoteEvent")
local countdown = 5
-- Dispara o RemoteEvent a cada segundo até que o tempo acabe
for timeRemaining = -1, countdown do
remoteEvent:FireAllClients(countdown - timeRemaining)
task.wait(1)
end

Callbacks remotos

Um objeto RemoteFunction facilita comunicação síncrona, bidirecional através da fronteira cliente-servidor. O remetente de uma função remota irá esperar até receber uma resposta do destinatário.

Para criar uma nova RemoteFunction através da janela Explorer no Studio:

  1. Passe o mouse sobre o contêiner em que você deseja inserir o RemoteFunction. Para garantir que tanto o servidor quanto o cliente tenham acesso, ele deve estar em um lugar onde ambos os lados possam vê-lo, como ReplicatedStorage, embora em alguns casos seja apropriado armazená-lo em Workspace ou dentro de um Tool.
  2. Clique no botão que aparece à direita do nome do contêiner e insira uma instância de RemoteFunction.
  3. Renomeie a instância para descrever seu propósito.

Uma vez que você criou um RemoteFunction, ele pode facilitar a comunicação bidirecional entre cliente e servidor ou entre servidor e cliente.

Cliente → Servidor → Cliente
Servidor → Cliente → Servidor

Cliente → servidor → cliente

Você pode usar um LocalScript para chamar uma função no servidor chamando o método InvokeServer() em um RemoteFunction. Ao contrário de um evento remoto, o LocalScript que invoca o RemoteFunction espera até que o callback retorne. Os argumentos que você passa para InvokeServer() são passados para o callback de OnServerInvoke com certas limitações. Note que se você definir múltiplos callbacks para o mesmo RemoteFunction, apenas a última definição será executada.

ClienteRemoteFunction:InvokeServer(args)
ServidorRemoteFunction.OnServerInvoke = function(player, args)

O seguinte Script define a função de callback através de OnServerInvoke e retorna a Part solicitada através de seu valor de return. O LocalScript correspondente então chama InvokeServer() com argumentos extras definindo a cor e a posição da peça solicitada.

Conexão de Callback - Script

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Workspace = game:GetService("Workspace")
-- Obter referência à instância da função remota
local remoteFunction = ReplicatedStorage:FindFirstChildOfClass("RemoteFunction")
-- Função de callback
local function createPart(player, partColor, partPosition)
print(player.Name .. " solicitou uma nova peça")
local newPart = Instance.new("Part")
newPart.Color = partColor
newPart.Position = partPosition
newPart.Parent = Workspace
return newPart
end
-- Definir função como callback da função remota
remoteFunction.OnServerInvoke = createPart
Invocação de Evento - LocalScript

local ReplicatedStorage = game:GetService("ReplicatedStorage")
-- Obter referência à instância da função remota
local remoteFunction = ReplicatedStorage:FindFirstChildOfClass("RemoteFunction")
-- Passar uma cor e posição ao invocar o callback
local newPart = remoteFunction:InvokeServer(Color3.fromRGB(255, 0, 0), Vector3.new(0, 25, -20))
-- Exibir a referência da peça retornada
print("O servidor criou a peça solicitada:", newPart)

Servidor → cliente → servidor

Você pode usar um Script para chamar uma função no cliente chamando o método InvokeClient() em um RemoteFunction, mas isso tem sérios riscos como segue:

  • Se o cliente lançar um erro, o servidor também lançará o erro.
  • Se o cliente desconectar enquanto está sendo invocado, InvokeClient() lança um erro.
  • Se o cliente não retornar um valor, o servidor espera para sempre.

Para ações que não requerem comunicações bidirecionais, como atualizar uma interface gráfica, use um RemoteEvent e comunique-se do servidor para o cliente.

Limitações de argumento

Quando você dispara um RemoteEvent ou invoca um RemoteFunction, ele encaminha quaisquer argumentos que você passar com o evento ou para a função de callback. Qualquer tipo de objeto Roblox, como um Enum, Instance, ou outros podem ser passados, assim como tipos Luau, como números, strings e booleanos, embora você deva explorar cuidadosamente as seguintes limitações.

Índices não string

Se quaisquer índices de uma tabela passada forem tipos não string, como um Instance, userdata ou função, o Roblox automaticamente converte esses índices para strings.

Conexão de Evento - LocalScript

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local remoteEvent = ReplicatedStorage:FindFirstChildOfClass("RemoteEvent")
local function onEventFire(passedTable)
for k, v in passedTable do
print(typeof(k)) --> string
end
end
-- Conectar função ao evento
remoteEvent.OnClientEvent:Connect(onEventFire)
Disparo de Evento - Script

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")
local Workspace = game:GetService("Workspace")
local remoteEvent = ReplicatedStorage:FindFirstChildOfClass("RemoteEvent")
-- Ouvir jogadores que entram e despachar evento remoto para cada um
local function onPlayerAdded(player)
remoteEvent:FireClient(player,
{
[Workspace.Baseplate] = true
}
)
end
Players.PlayerAdded:Connect(onPlayerAdded)

Funções passadas

Funções incluídas como argumentos para um RemoteEvent ou RemoteFunction não serão replicadas através da fronteira cliente-servidor, tornando impossível passar funções remotamente. Em vez disso, o argumento resultante no lado receptor será nil.

Conexão de Evento - LocalScript

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local remoteEvent = ReplicatedStorage:FindFirstChildOfClass("RemoteEvent")
local function onClientEvent(func)
print(func) --> nil
end
remoteEvent.OnClientEvent:Connect(onClientEvent)
Disparo de Evento - Script

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local remoteEvent = ReplicatedStorage:FindFirstChildOfClass("RemoteEvent")
local function testFunction()
print("Olá mundo!")
end
-- Dispare o evento remoto com função como argumento
remoteEvent:FireAllClients(testFunction)

Indexação de tabelas

Se você passar uma tabela de dados, não passe uma tabela mista de chaves numéricas e strings. Em vez disso, passe uma tabela que consiste inteiramente em pares chave-valor (dicionário) ou inteiramente de índices numéricos.

Conexão de Evento - Script

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local remoteEvent = ReplicatedStorage:FindFirstChildOfClass("RemoteEvent")
local function onEventFire(player, passedTable)
for k, v in passedTable do
print(k .. " = " .. v)
--> 1 = Espada
--> 2 = Arco
--> CharName = Diva Dragonslayer
--> CharClass = Rogue
end
end
-- Conectar função ao evento
remoteEvent.OnServerEvent:Connect(onEventFire)
Disparo de Evento - LocalScript

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local remoteEvent = ReplicatedStorage:FindFirstChildOfClass("RemoteEvent")
-- Tabela indexada numericamente
local inventoryData = {
"E espada", "Arco"
}
-- Tabela dicionário
local characterData = {
CharName = "Diva Dragonslayer",
CharClass = "Rogue"
}
remoteEvent:FireServer(inventoryData)
remoteEvent:FireServer(characterData)

Identidades de tabelas

Tabelas passadas como argumentos para eventos/callbacks remotos são copiadas, o que significa que não serão exatamente equivalentes àquelas fornecidas ao disparar o evento ou invocar o callback. Da mesma forma, tabelas retornadas ao invocador não serão exatamente equivalentes às fornecidas. Você pode demonstrar isso rodando o seguinte script em um RemoteFunction e observando como as identidades das tabelas diferem.

Conexão de Callback - Script

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local remoteFunction = ReplicatedStorage:FindFirstChildOfClass("RemoteFunction")
-- Função de callback
local function returnTable(player, passedTable)
-- Exibir identidade da tabela na invocação
print(tostring(passedTable)) --> table: 0x48eb7aead27563d9
return passedTable
end
-- Definir função como callback da função remota
remoteFunction.OnServerInvoke = returnTable
Invocação de Evento - LocalScript

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local remoteFunction = ReplicatedStorage:FindFirstChildOfClass("RemoteFunction")
local inventoryData = {
"E espada", "Arco"
}
-- Exibir identidade da tabela original
print(tostring(inventoryData)) --> table: 0x059bcdbb2b576549
local invokeReturn = remoteFunction:InvokeServer(inventoryData)
-- Exibir identidade da tabela ao retornar
print(tostring(invokeReturn)) --> table: 0x9fcae7919563a0e9

Metatables

Se uma tabela tiver uma metatable, todas as informações da metatable são perdidas na transferência. No seguinte exemplo de código, a propriedade NumWheels faz parte da metatable Car. Quando o servidor recebe a seguinte tabela, a tabela truck tem a propriedade Name, mas não a propriedade NumWheels.

Conexão de Evento - Script

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local remoteEvent = ReplicatedStorage:FindFirstChildOfClass("RemoteEvent")
local function onEvent(player, param)
print(param) --> {["Name"] = "MyTruck"}
end
-- Conectar função ao evento
remoteEvent.OnServerEvent:Connect(onEvent)
Disparo de Evento - LocalScript

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local remoteEvent = ReplicatedStorage:FindFirstChildOfClass("RemoteEvent")
local Car = {}
Car.NumWheels = 4
Car.__index = Car
local truck = {}
truck.Name = "MyTruck"
setmetatable(truck, Car)
-- Dispara evento com tabela incluindo uma metatable
remoteEvent:FireServer(truck)

Instâncias não replicadas

Se um RemoteEvent ou RemoteFunction passar um valor que é visível apenas para o remetente, o Roblox não o replica na fronteira cliente-servidor e passa nil em vez do valor. Por exemplo, se um Script passar um descendente de ServerStorage, o cliente que escuta o evento receberá um valor nil porque esse objeto não é replicável para o cliente.

Disparo de Evento - Script

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local ServerStorage = game:GetService("ServerStorage")
local Players = game:GetService("Players")
local remoteEvent = ReplicatedStorage:FindFirstChildOfClass("RemoteEvent")
-- Será recebido como "nil" porque o cliente não pode acessar ServerStorage
local storedPart = Instance.new("Part")
storedPart.Parent = ServerStorage
local function onPlayerAdded(player)
remoteEvent:FireClient(player, storedPart)
end
Players.PlayerAdded:Connect(onPlayerAdded)

Da mesma forma, se você criar uma peça em um LocalScript e tentar passá-la para um Script, o servidor verá nil porque a peça não é replicável para o servidor.

Disparo de Evento - LocalScript

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Workspace = game:GetService("Workspace")
local remoteEvent = ReplicatedStorage:FindFirstChildOfClass("RemoteEvent")
-- Será recebido como "nil" porque o servidor não conhece essa peça
local clientPart = Instance.new("Part")
clientPart.Parent = Workspace
remoteEvent:FireServer(clientPart)
©2026 Roblox Corporation, Roblox, o logotipo Roblox e Powering Imagination estão entre nossas marcas registradas e não registradas nos EUA e em outros países.