Zdalne zdarzenia i wywołania zwrotne

*Ta zawartość została przetłumaczona przy użyciu narzędzi AI (w wersji beta) i może zawierać błędy. Aby wyświetlić tę stronę w języku angielskim, kliknij tutaj.

Gry Roblox są domyślnie wieloosobowe, więc wszystkie gry z natury komunikują się między serwerem a podłączonymi klientami graczy. W najprostszym przypadku, gdy gracze poruszają swoimi postaciami, niektóre właściwości Humanoid, takie jak stany, są komunikowane do serwera, który przekazuje te informacje innym połączonym klientom.

Zdalne zdarzenia i wywołania zwrotne umożliwiają komunikację w obrębie granicy klient-serwer:

  • RemoteEvents umożliwiają komunikację jednokierunkową (wysłanie żądania i nie czekanie na odpowiedź).
  • UnreliableRemoteEvents umożliwiają jednokierunkową komunikację dla danych, które zmieniają się ciągle lub nie są kluczowe dla stanu gry. Te zdarzenia wymieniają porządek i niezawodność na poprawioną wydajność sieci.
  • RemoteFunctions umożliwiają komunikację dwukierunkową (wysłanie żądania i czekanie na odpowiedź od odbiorcy).

W przeciwieństwie do zdarzeń wiązanych, które mają bardziej ograniczone zastosowanie, przypadki użycia zdalnych zdarzeń i funkcji są zbyt liczne, aby je wypisać:

  • Rozgrywka - Podstawowa rozgrywka, taka jak osiągnięcie przez gracza końca poziomu, może wymagać zdalnego zdarzenia. Skrypt klienta powiadamia serwer, a skrypty serwera resetują pozycję gracza.
  • Weryfikacja serwera - Jeśli gracz próbuje wypić miksturę, czy naprawdę ma tę miksturę? Aby zapewnić sprawiedliwość, serwer musi być źródłem prawdy dla gry. Skrypt klienta może użyć zdalnego zdarzenia, aby powiadomić serwer, że gracz pije miksturę, a następnie skrypty serwera mogą zdecydować, czy gracz rzeczywiście ma tę miksturę i czy przyznać jakiekolwiek korzyści.
  • Aktualizacje interfejsu użytkownika - Gdy stan gry się zmienia, skrypty serwera mogą używać zdalnych zdarzeń, aby powiadomić klientów o zmianach wyniku, celach itp.
  • Zakupy na rynku w grze - Aby uzyskać przykład implementacji, która korzysta z zdalnych funkcji, zobacz Zakupy subskrypcyjne.

Szybki przewodnik

Poniższe tabele służą jako szybki przewodnik po tym, jak używać RemoteEvents i RemoteFunctions, aby komunikować się między klientem a serwerem.

Klient → Serwer
KlientRemoteEvent:FireServer(args)
SerwerRemoteEvent.OnServerEvent:Connect(function(player, args))
Serwer → Klient
SerwerRemoteEvent:FireClient(player, args)
KlientRemoteEvent.OnClientEvent:Connect(function(args))
Serwer → Wszyscy klienci
SerwerRemoteEvent:FireAllClients(args)
KlientRemoteEvent.OnClientEvent:Connect(function(args))

Zdarzenia zdalne

Obiekt RemoteEvent ułatwia asynchroniczną, jednokierunkową komunikację w obrębie granicy klient-serwer bez czekania na odpowiedź.

Aby stworzyć nowe RemoteEvent przez okno Eksploratora w Studio:

  1. Najedź na kontener, do którego chcesz wstawić RemoteEvent. Aby zapewnić dostęp serwera i klienta, musi być w miejscu, w którym obie strony mogą go zobaczyć, na przykład w ReplicatedStorage, chociaż w niektórych przypadkach odpowiednie jest przechowywanie go w Workspace lub w Tool.
  2. Kliknij przycisk , który pojawi się po prawej stronie nazwy kontenera, i wstaw instancję RemoteEvent.
  3. Zmień nazwę instancji, aby opisać jej cel.

Po utworzeniu RemoteEvent może on ułatwiać jednokierunkową komunikację z klienta do serwera, z serwera do klienta lub z serwera do wszystkich klientów.

Klient → Serwer
Serwer → Klient
Serwer → Wszyscy klienci

Klient → serwer

Możesz użyć LocalScript, aby wywołać zdarzenie na serwerze, wywołując metodę FireServer() na RemoteEvent. Jeśli przekazujesz argumenty do FireServer(), są one przekazywane do obsługi zdarzenia na serwerze z pewnymi ograniczeniami. Zauważ, że pierwszy parametr obsługi zdarzenia na serwerze to zawsze obiekt Player klienta, który go wywołuje, a dodatkowe parametry następują po nim.

KlientRemoteEvent:FireServer(args)
SerwerRemoteEvent.OnServerEvent:Connect(function(player, args))

Poniższy Script łączy obsługę zdarzenia z OnServerEvent, która tworzy nowy Part na serwerze. Towarzyszący mu LocalScript wywołuje wtedy FireServer() na instancji RemoteEvent z pożądaną Color i Position dla tej części.

Połączenie zdarzenia - Script

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Workspace = game:GetService("Workspace")
-- Uzyskaj referencję do instancji zdarzenia zdalnego
local remoteEvent = ReplicatedStorage:FindFirstChildOfClass("RemoteEvent")
local function onCreatePart(player, partColor, partPosition)
print(player.Name .. " wywołał RemoteEvent")
local newPart = Instance.new("Part")
newPart.Color = partColor
newPart.Position = partPosition
newPart.Parent = Workspace
end
-- Połącz funkcję z wydarzeniem
remoteEvent.OnServerEvent:Connect(onCreatePart)
Uruchamianie zdarzenia - LocalScript

local ReplicatedStorage = game:GetService("ReplicatedStorage")
-- Uzyskaj referencję do instancji zdarzenia zdalnego
local remoteEvent = ReplicatedStorage:FindFirstChildOfClass("RemoteEvent")
-- Uruchom zdarzenie zdalne i przekaż dodatkowe argumenty
remoteEvent:FireServer(Color3.fromRGB(255, 0, 0), Vector3.new(0, 25, -20))

Serwer → klient

Możesz użyć Script, aby wywołać zdarzenie na kliencie, wywołując metodę FireClient() na RemoteEvent. Pierwszym argumentem dla FireClient() jest obiekt Player klienta, który ma zareagować na zdarzenie, a dodatkowe argumenty są przekazywane do klienta z pewnymi ograniczeniami. Zauważ, że obsługa zdarzenia nie musi zawierać obiektu Player jako pierwszego argumentu, ponieważ możesz zidentyfikować gracza na kliencie przy użyciu Players.LocalPlayer.

SerwerRemoteEvent:FireClient(player, args)
KlientRemoteEvent.OnClientEvent:Connect(function(args))

Poniższy LocalScript łączy obsługę zdarzenia z OnClientEvent. Towarzyszący mu Script nasłuchuje na przychodzących graczy do serwera i wywołuje FireClient() dla każdego z nich z dowolnymi danymi.

Połączenie zdarzenia - LocalScript

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")
-- Uzyskaj referencję do instancji zdarzenia zdalnego
local remoteEvent = ReplicatedStorage:FindFirstChildOfClass("RemoteEvent")
local player = Players.LocalPlayer
local function onNotifyPlayer(maxPlayers, respawnTime)
print("[Klient] Zdarzenie odebrane przez gracza", player.Name)
print(maxPlayers, respawnTime)
end
-- Połącz funkcję z wydarzeniem
remoteEvent.OnClientEvent:Connect(onNotifyPlayer)
Uruchamianie zdarzenia - Script

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")
-- Uzyskaj referencję do instancji zdarzenia zdalnego
local remoteEvent = ReplicatedStorage:FindFirstChildOfClass("RemoteEvent")
-- Nasłuchuj na przychodzących graczy i wysyłaj zdarzenie zdalne do każdego
local function onPlayerAdded(player)
print("[Serwer] Wywołanie zdarzenia dla gracza", player.Name)
remoteEvent:FireClient(player, Players.MaxPlayers, Players.RespawnTime)
end
Players.PlayerAdded:Connect(onPlayerAdded)

Serwer → wszyscy klienci

Możesz użyć Script, aby wywołać zdarzenie wśród wszystkich klientów, wywołując metodę FireAllClients() na RemoteEvent. W przeciwieństwie do FireClient(), metoda FireAllClients() nie wymaga obiektu Player, ponieważ wyzwala RemoteEvent do wszystkich klientów.

SerwerRemoteEvent:FireAllClients(args)
KlientRemoteEvent.OnClientEvent:Connect(function(args))

Poniższy LocalScript łączy obsługę zdarzenia z OnClientEvent, które wypisuje pozostały czas odliczania. Towarzyszący mu Script wywołuje wtedy FireAllClients() w pętli co sekundę, aby wywołać RemoteEvent dla wszystkich klientów.

Połączenie zdarzenia - LocalScript

local ReplicatedStorage = game:GetService("ReplicatedStorage")
-- Uzyskaj referencję do instancji zdarzenia zdalnego
local remoteEvent = ReplicatedStorage:FindFirstChildOfClass("RemoteEvent")
local function onTimerUpdate(seconds)
print(seconds)
end
-- Połącz funkcję z wydarzeniem
remoteEvent.OnClientEvent:Connect(onTimerUpdate)
Uruchamianie zdarzenia - Script

local ReplicatedStorage = game:GetService("ReplicatedStorage")
-- Uzyskaj referencję do instancji zdarzenia zdalnego
local remoteEvent = ReplicatedStorage:FindFirstChildOfClass("RemoteEvent")
local countdown = 5
-- Wywołuj RemoteEvent co sekundę aż czas się skończy
for timeRemaining = -1, countdown do
remoteEvent:FireAllClients(countdown - timeRemaining)
task.wait(1)
end

Wywołania zwrotne zdalne

Obiekt RemoteFunction ułatwia synchroniczną, dwukierunkową komunikację w obrębie granicy klient-serwer. Nadawca zdalnej funkcji wstrzymuje działanie aż do momentu, gdy otrzyma odpowiedź od odbiorcy.

Aby stworzyć nowe RemoteFunction przez okno Eksploratora w Studio:

  1. Najedź na kontener, do którego chcesz wstawić RemoteFunction. Aby zapewnić dostęp serwera i klienta, musi być w miejscu, w którym obie strony mogą go zobaczyć, na przykład w ReplicatedStorage, chociaż w niektórych przypadkach odpowiednie jest przechowywanie go w Workspace lub w Tool.
  2. Kliknij przycisk , który pojawi się po prawej stronie nazwy kontenera, i wstaw instancję RemoteFunction.
  3. Zmień nazwę instancji, aby opisać jej cel.

Po utworzeniu RemoteFunction może on ułatwiać dwukierunkową komunikację między klientem a serwerem lub między serwerem a klientem.

Klient → Serwer → Klient
Serwer → Klient → Serwer

Klient → serwer → klient

Możesz użyć LocalScript, aby wywołać funkcję na serwerze, wywołując metodę InvokeServer() na RemoteFunction. W przeciwieństwie do zdarzenia zdalnego, LocalScript, który wywołuje RemoteFunction, wstrzymuje działanie, aż wywołanie zwrotne się zakończy. Argumenty, które przekazujesz do InvokeServer(), są przekazywane do OnServerInvoke wywołania zwrotnego RemoteFunction z pewnymi ograniczeniami. Zauważ, że jeśli zdefiniujesz wiele wywołań zwrotnych dla tej samej RemoteFunction, tylko ostatnia definicja zostanie wywołana.

KlientRemoteFunction:InvokeServer(args)
SerwerRemoteFunction.OnServerInvoke = function(player, args)

Poniższy Script definiuje funkcję wywołania zwrotnego za pomocą OnServerInvoke i zwraca żądany Part przez wartość return. Towarzyszący mu LocalScript wywołuje następnie InvokeServer() z dodatkowymi argumentami definiującymi kolor i położenie żądanej części.

Połączenie wywołania zwrotnego - Script

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Workspace = game:GetService("Workspace")
-- Uzyskaj referencję do instancji funkcji zdalnej
local remoteFunction = ReplicatedStorage:FindFirstChildOfClass("RemoteFunction")
-- Funkcja wywołania zwrotnego
local function createPart(player, partColor, partPosition)
print(player.Name .. " poprosił o nową część")
local newPart = Instance.new("Part")
newPart.Color = partColor
newPart.Position = partPosition
newPart.Parent = Workspace
return newPart
end
-- Ustaw funkcję jako wywołanie zwrotne funkcji zdalnej
remoteFunction.OnServerInvoke = createPart
Wywołanie zdarzenia - LocalScript

local ReplicatedStorage = game:GetService("ReplicatedStorage")
-- Uzyskaj referencję do instancji funkcji zdalnej
local remoteFunction = ReplicatedStorage:FindFirstChildOfClass("RemoteFunction")
-- Przekaż kolor i pozycję podczas wywoływania wywołania zwrotnego
local newPart = remoteFunction:InvokeServer(Color3.fromRGB(255, 0, 0), Vector3.new(0, 25, -20))
-- Wypisz zwróconą referencję do części
print("Serwer stworzył żądaną część:", newPart)

Serwer → klient → serwer

Możesz użyć Script, aby wywołać funkcję na kliencie, wywołując metodę InvokeClient() na RemoteFunction, ale niesie to poważne ryzyka, takie jak:

  • Jeśli klient wyrzuci błąd, to serwer również wyrzuci błąd.
  • Jeśli klient odłączy się podczas wywołania, InvokeClient() wyrzuca błąd.
  • Jeśli klient nie zwróci wartości, serwer wstrzymuje działanie na zawsze.

W przypadku działań, które nie wymagają dwukierunkowej komunikacji, takich jak aktualizacja GUI, użyj RemoteEvent i komunikuj się z serwera do klienta.

Ograniczenia argumentów

Gdy wywołujesz RemoteEvent lub wywołujesz RemoteFunction, przesyła on wszelkie argumenty, które przekazujesz z zdarzeniem lub do funkcji zwrotnej. Można przesyłać wszelkie typy obiektów Roblox, takie jak Enum, Instance lub inne, a także typy Luau, takie jak liczby, ciągi i wartości logiczne, chociaż powinieneś dokładnie zbadać następujące ograniczenia.

Indeksy niezawodowe

Jeśli jakiekolwiek indeksy przekazywanej tabeli są typami niezawodowymi, takimi jak Instance, userdata lub funkcja, Roblox automatycznie przekształca te indeksy na ciągi.

Połączenie zdarzenia - 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
-- Połącz funkcję z wydarzeniem
remoteEvent.OnClientEvent:Connect(onEventFire)
Uruchamianie zdarzenia - Script

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")
local Workspace = game:GetService("Workspace")
local remoteEvent = ReplicatedStorage:FindFirstChildOfClass("RemoteEvent")
-- Nasłuchuj na przychodzących graczy i wysyłaj zdarzenie zdalne do każdego
local function onPlayerAdded(player)
remoteEvent:FireClient(player,
{
[Workspace.Baseplate] = true
}
)
end
Players.PlayerAdded:Connect(onPlayerAdded)

Przekazywane funkcje

Funkcje zawarte jako argumenty dla RemoteEvent lub RemoteFunction nie będą replikowane przez granicę klient-serwer, co uniemożliwia ich zdalne przesyłanie. Zamiast tego otrzymany argument po stronie odbierającej będzie nil.

Połączenie zdarzenia - LocalScript

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

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local remoteEvent = ReplicatedStorage:FindFirstChildOfClass("RemoteEvent")
local function testFunction()
print("Cześć, świecie!")
end
-- Uruchom zdarzenie zdalne z funkcją jako argument
remoteEvent:FireAllClients(testFunction)

Indeksowanie tabeli

Jeśli przekazujesz tabelę danych, nie przesyłaj mieszanej tabeli z indeksami numerycznymi i ciągowymi. Zamiast tego przekaż tabelę składającą się wyłącznie z par klucz-wartość (słownik) lub wyłącznie z indeksów numerycznych.

Połączenie zdarzenia - 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 = Miecz
--> 2 = Łuk
--> CharName = Diva Smoczy Zabójca
--> CharClass = Złodziejaszek
end
end
-- Połącz funkcję z wydarzeniem
remoteEvent.OnServerEvent:Connect(onEventFire)
Uruchamianie zdarzenia - LocalScript

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local remoteEvent = ReplicatedStorage:FindFirstChildOfClass("RemoteEvent")
-- Tabela indeksowana numerycznie
local inventoryData = {
"Miecz", "Łuk"
}
-- Tabela słownikowa
local characterData = {
CharName = "Diva Smoczy Zabójca",
CharClass = "Złodziejaszek"
}
remoteEvent:FireServer(inventoryData)
remoteEvent:FireServer(characterData)

Identyczność tabeli

Tabele przekazywane jako argumenty do zdalnych zdarzeń/wywołań zwrotnych są kopiowane, co oznacza, że nie będą dokładnie równe tym, które dostarczono podczas wyzwalania zdarzenia lub wywołania wywołania zwrotnego. Tabele zwrócone do wywołującego również nie będą dokładnie równe tym, które dostarczono. Możesz to pokazać, uruchamiając poniższy skrypt na RemoteFunction i obserwując, jak różnią się identyfikatory tabel.

Połączenie wywołania zwrotnego - Script

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local remoteFunction = ReplicatedStorage:FindFirstChildOfClass("RemoteFunction")
-- Funkcja wywołania zwrotnego
local function returnTable(player, passedTable)
-- Wypisz identyfikator tabeli podczas wywołania
print(tostring(passedTable)) --> tabela: 0x48eb7aead27563d9
return passedTable
end
-- Ustaw funkcję jako wywołanie zwrotne funkcji zdalnej
remoteFunction.OnServerInvoke = returnTable
Wywołanie zdarzenia - LocalScript

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local remoteFunction = ReplicatedStorage:FindFirstChildOfClass("RemoteFunction")
local inventoryData = {
"Miecz", "Łuk"
}
-- Wypisz oryginalny identyfikator tabel
print(tostring(inventoryData)) --> tabela: 0x059bcdbb2b576549
local invokeReturn = remoteFunction:InvokeServer(inventoryData)
-- Wypisz identyfikator tabeli po zwrocie
print(tostring(invokeReturn)) --> tabela: 0x9fcae7919563a0e9

Metatable

Jeśli tabela ma metatabelę, wszystkie informacje z metatabeli są tracone w transferze. W poniższym przykładzie kodu właściwość NumWheels jest częścią metatabeli Car. Gdy serwer otrzymuje następującą tabelę, tabela truck ma właściwość Name, ale nie ma właściwości NumWheels.

Połączenie zdarzenia - Script

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local remoteEvent = ReplicatedStorage:FindFirstChildOfClass("RemoteEvent")
local function onEvent(player, param)
print(param) --> {["Name"] = "MójCiężarówka"}
end
-- Połącz funkcję z wydarzeniem
remoteEvent.OnServerEvent:Connect(onEvent)
Uruchamianie zdarzenia - LocalScript

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local remoteEvent = ReplicatedStorage:FindFirstChildOfClass("RemoteEvent")
local Car = {}
Car.NumWheels = 4
Car.__index = Car
local truck = {}
truck.Name = "MójCiężarówka"
setmetatable(truck, Car)
-- Uruchom zdarzenie z tabelą zawierającą metatabelę
remoteEvent:FireServer(truck)

Instancje, które nie są replikowane

Jeśli RemoteEvent lub RemoteFunction przekaże wartość, która jest widoczna tylko dla nadawcy, Roblox nie replikuje jej przez granicę klient-serwer i zamiast tego przekazuje nil zamiast wartości. Na przykład, jeśli Script przekaże potomka ServerStorage, klient nasłuchujący zdarzenia otrzyma wartość nil, ponieważ ten obiekt nie jest replikowany dla klienta.

Uruchamianie zdarzenia - Script

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local ServerStorage = game:GetService("ServerStorage")
local Players = game:GetService("Players")
local remoteEvent = ReplicatedStorage:FindFirstChildOfClass("RemoteEvent")
-- Zostanie odebrane jako "nil", ponieważ klient nie ma dostępu do ServerStorage
local storedPart = Instance.new("Part")
storedPart.Parent = ServerStorage
local function onPlayerAdded(player)
remoteEvent:FireClient(player, storedPart)
end
Players.PlayerAdded:Connect(onPlayerAdded)

Podobnie, jeśli stworzysz część w LocalScript i spróbujesz ją przekazać do Script, serwer zobaczy nil, ponieważ część nie jest replikowana dla serwera.

Uruchamianie zdarzenia - LocalScript

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Workspace = game:GetService("Workspace")
local remoteEvent = ReplicatedStorage:FindFirstChildOfClass("RemoteEvent")
-- Zostanie odebrane jako "nil", ponieważ serwer nie wie o tej części
local clientPart = Instance.new("Part")
clientPart.Parent = Workspace
remoteEvent:FireServer(clientPart)
©2026 Roblox Corporation. Nazwa Roblox, logo Roblox oraz hasło „Powering Imagination” należą do naszych zarejestrowanych i niezarejestrowanych znaków towarowych na terenie Stanów Zjednoczonych oraz w innych krajach.