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.

Todas as experiências intrinsecamente se comunicam entre o servidor e os clientes dos jogadores. Por exemplo, à medida que um jogador manipula seu personagem em seu cliente , certas Humanoid propriedades, como estados, são comunicadas ao servidor , que passa essa informação para os outros clientes conectados .

RemoteEvent e RemoteFunction objetos permitem que você crie seus próprios eventos e funções de chamada de volta para comunicar comportamento personalizado em todo o limite cliente-servidor, com RemoteEvents facilitando a comunicação unidirecional e RemoteFunctions facilitando a comunicação bidirecional (enviando uma solicitação através do limite e respondendo até que uma resposta seja recebida do destinatário).

Referência Rápida

As seguintes tabelas servem como uma referência rápida para como usar RemoteEvents e RemoteFunctions para se 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 a comunicação assíncrona e unidirecional através do limite cliente-servidor sem ceder a uma resposta.

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

  1. Passe o mouse sobre o recipiente no qual você deseja inserir o RemoteEvent . Para garantir o acesso do servidor e do cliente, 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 RemoteEvent .
  3. Renomeie a instância para descrever seu propósito.

Depois de criar um RemoteEvent, ele pode facilitar a comunicação unidirecional de cliente para servidor, de servidor para cliente ou do servidor para todos os clientes.

Cliente → Servidor
Servidor → Cliente
Servidor → Todos os Clientes

Cliente → Servidor

Você pode usar um LocalScript para desencadear um evento no servidor chamando o FireServer() método em um RemoteEvent . Se você passar argumentos para FireServer() , eles passam 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 do cliente que o chama, e parâmetros adicionais seguir.

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

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

Conexão de Evento - Script

local ReplicatedStorage = game:GetService("ReplicatedStorage")
-- Obter referência à instância de evento remoto
local remoteEvent = ReplicatedStorage:FindFirstChildOfClass("RemoteEvent")
local function onCreatePart(player, partColor, partPosition)
print(player.Name .. " fired the 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)
Lançamento de Evento - LocalScript

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

Servidor → Cliente

Você pode usar um Script para acionar um evento em um cliente chamando o FireClient() método em um RemoteEvent . O primeiro argumento para FireClient() é o Player objeto do cliente que você deseja responder ao evento, e argumentos adicionais são passados para o cliente com certas limitações . Observe que o manipulador de eventos não precisa incluir o Player objeto como seu primeiro argumento, pois 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 OnClientEvent evento. O acompanhante Script então ouve os 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 de evento remoto
local remoteEvent = ReplicatedStorage:FindFirstChildOfClass("RemoteEvent")
local player = Players.LocalPlayer
local function onNotifyPlayer(maxPlayers, respawnTime)
print("[Client] Event received by player", 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 de evento remoto
local remoteEvent = ReplicatedStorage:FindFirstChildOfClass("RemoteEvent")
-- Ouça os jogadores recebidos e envie um evento remoto para cada um deles
local function onPlayerAdded(player)
print("[Server] Firing event to player", player.Name)
remoteEvent:FireClient(player, Players.MaxPlayers, Players.RespawnTime)
end
Players.PlayerAdded:Connect(onPlayerAdded)

Servidor → Todos os Clientes

Você pode usar um Script para desencadear um evento em todos os clientes chamando o FireAllClients() método em um RemoteEvent . Ao contrário de FireClient() , o FireAllClients() método não requer um Player objeto 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 OnClientEvent evento que emite um tempo de contagem regressiva restante. O acompanhante Script 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 de 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 de evento remoto
local remoteEvent = ReplicatedStorage:FindFirstChildOfClass("RemoteEvent")
local countdown = 5
-- Atire no RemoteEvent a cada segundo até o tempo expirar
for timeRemaining = -1, countdown do
remoteEvent:FireAllClients(countdown - timeRemaining)
task.wait(1)
end

Retornos de Chamadas Remotas

Um objeto RemoteFunction facilita a comunicação síncrona e bidirecional através do limite cliente-servidor. O remetente de uma função remota cederá até receber uma resposta do destinatário.

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

  1. Passe o mouse sobre o recipiente no qual você deseja inserir o RemoteFunction . Para garantir o acesso do servidor e do cliente, 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 RemoteFunction .
  3. Renomeie a instância para descrever seu propósito.

Depois de criar 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 InvokeServer() método em um RemoteFunction . Ao contrário de um evento remoto , o LocalScript que invoca os rendimentos de RemoteFunction até o retorno da chamada. Os argumentos que você passa para InvokeServer() passam para o OnServerInvoke retorno do RemoteFunction com certas limitações . Observe que se você definir vários callbacks para o mesmo RemoteFunction , apenas a última definição é ejecutada.

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

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

Conexão de retorno de chamada - Script

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

local ReplicatedStorage = game:GetService("ReplicatedStorage")
-- Obter referência à instância de função remota
local remoteFunction = ReplicatedStorage:FindFirstChildOfClass("RemoteFunction")
-- Passe uma cor e posição ao invocar o retorno de chamada
local newPart = remoteFunction:InvokeServer(Color3.fromRGB(255, 0, 0), Vector3.new(0, 25, -20))
-- Saída da referência da peça retornada
print("The server created the requested part:", newPart)

Servidor → Cliente → Server

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

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

Limitações de Argumentos

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

Índices Não-Cordas

Se qualquer índice de uma tabela passada for de tipo não-string, como Instance , userdata , ou função , Roblox automaticamente converte esses índices em 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 / cadeia / texto
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 remoteEvent = ReplicatedStorage:FindFirstChildOfClass("RemoteEvent")
-- Ouça os jogadores recebidos e envie um evento remoto para cada um deles
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 do limite cliente-servidor, tornando impossível passar funções remotamente. Em vez disso, o argumento resultante no lado de recebimento será nil .

Conexão de Evento - LocalScript

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

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local remoteEvent = ReplicatedStorage:FindFirstChildOfClass("RemoteEvent")
local function testFunction()
print("Hello world!")
end
-- Atire o evento remoto com a função como argumento
remoteEvent:FireAllClients(testFunction)

Indexação da tabela

Se você passar uma tabela de dados, não passe uma tabela mista de teclas numéricas e de string. Em vez disso, passe uma tabela que consiste em inteiramente de pares de valores-chave (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 Dragão Assassino
--> CharClass = Rogue
end
end
-- Conectar função ao evento
remoteEvent.OnServerEvent:Connect(onEventFire)
Lançamento de Evento - LocalScript

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

Identidades da Tabela

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

Conexão de retorno de chamada - Script

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

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local remoteFunction = ReplicatedStorage:FindFirstChildOfClass("RemoteFunction")
local inventoryData = {
"Sword", "Bow"
}
-- Saída da identidade original da mesa
print(tostring(inventoryData)) --> tabela: 0x059bcdbb2b576549
local invokeReturn = remoteFunction:InvokeServer(inventoryData)
-- Saída da identidade da mesa ao retornar
print(tostring(invokeReturn)) --> table: 0x9fcae7919563a0e9

Metatábulos

Se uma tabela tiver uma metabilitável, todas as informações metabilitáveis serão perdidas na transferência. Na amostra de código a seguir, a propriedade NumWheels faz parte da metabilitável Car. Quando o servidor recebe a tabela a seguir, 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) -->
end
-- Conectar função ao evento
remoteEvent.OnServerEvent:Connect(onEvent)
Lançamento 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)
-- Evento de fogo com mesa incluindo um 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 através da fronteira cliente-servidor e passa nil em vez do valor. Por exemplo, se um Script passar um descendente de ServerStorage, o cliente que estiver ouvindo 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 "nulo" porque o cliente não pode acessar o 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 LocalScript e tentar passá-la para Script, o servidor verá nil porque a peça não é replicável para o servidor.

Lançamento de Evento - LocalScript

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local remoteEvent = ReplicatedStorage:FindFirstChildOfClass("RemoteEvent")
-- Será recebido como "nil" porque o servidor não sabe sobre essa parte
local clientPart = Instance.new("Part")
clientPart.Parent = workspace
remoteEvent:FireServer(clientPart)