Wydarzenia zdalne i wezwania powrotne

*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.

Doświadczenia Roblox są domyślnie wieloosobowe, więc wszystkie doświadczenia są z natury komunikowane między serwerem a połączonymi klientami graczy.W najprostszej sytuacji, gdy gracze przesuwają swoje postacie, pewne właściwości Humanoid stanów są przekazywane na serwer, który przekazuje tę informację innym połączonym klientom.

Wydarzenia zdalne i wezwania pozwalają na komunikację przez granicę klienta-serwera:

  • RemoteEvents włącz jednostronną komunikację (wysyłanie żądania i nie poddawanie się w odpowiedzi).
  • UnreliableRemoteEvents włącz jednostronną komunikację dla danych, które zmieniają się ciągle lub nie są krytyczne dla stanu gryTe wydarzenia handlują zamawianiem i niezawodnością w celu poprawy wykonywaniesieci.
  • RemoteFunctions włącz komunikację dwukierunkową (wysyłanie żądania i poddawanie, aż otrzymane zostanie odpowiedź od odbiorca).

W przeciwieństwie do wiązanych wydarzeń, które mają mniejszą użyteczność, przypadki użycia zdalnych wydarzeń i funkcji są zbyt liczne, aby je wymienić:

  • Grywalność - Podstawowa rozgrywka, tak jak gracz osiągający koniec poziomu, może wymagać zdarzenia zdalnego.Skrypt klienta powiadamia serwer, a skrypty serwera resetują pozycję gracza.
  • Weryfikacja serwera - Jeśli gracz próbuje wypić miksturę, czy rzeczywiście ma tę miksturę? Aby zapewnić uczciwość, serwer musi być źródłem prawdy dla doświadczenia.Skrypt klienta może używać zdarzenia zdalnego, aby powiadomić serwer, że gracz pije miksturę, a następnie skrypty serwera mogą decydować, czy gracz rzeczywiście ma tę miksturę i czy może przyznawać jakiekolwiek korzyści.
  • Aktualizacje interfejsu użytkownika - Wraz ze zmianą stanu gry skrypty serwera mogą używać zdarzeń zdalnych, aby powiadomić klientów o zmianach wyników, celów itp.
  • Zakupy na rynku doświadczeń - Dla przykładowej implementacji, która wykorzystuje zdalne funkcje, zobacz Prompt zakup subskrypcji.

Szybki odniesienie

Poniższe tabele służą jako szybkie odniesienie do tego, jak używać RemoteEvents i RemoteFunctions do komunikacji między klientem a serwerem.

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

Wydarzenia zdalne

Przedmiot RemoteEvent ułatwia asynchroniczną, jednostronną komunikację na granicy klient-serwer bez oddawania odpowiedzi.

Aby utworzyć nowy RemoteEvent za pomocą okna Explorer w Studio:

  1. Najedź na pojemnik, do którego chcesz wstawić RemoteEvent.Aby zapewnić dostęp zarówno serwera, jak i klienta, musi znajdować się w miejscu, w którym obie strony mogą go zobaczyć, takim jak ReplicatedStorage, choć w niektórych przypadkach właściwe jest przechowywanie go w Workspace lub wewnątrz Tool.
  2. Kliknij przycisk , który pojawia się po prawej stronie nazwy kontenera i wstaw instancję RemoteEvent .
  3. Zmień nazwę instancji, aby opisać jej cel.

Po utworzeniu RemoteEvent może ułatwić jednostronną komunikację z klienta na serwerze , z serwera do klienta lub z serwera do wszystkich klientów.

Klient → Serwer
>

Serwer → Klient
>

Serwer → Wszystkie klienty
>

Klient → serwer

Możesz użyć , aby uruchomić wydarzenie na serwerze poprzez wezwanie metody na .Jeśli przekażesz argumenty do FireServer(), przekażą się do menedżera zdarzeń na serwerze z pewnymi ograniczeniami .Zauważ, że pierwszy parametr obsługi zdarzenia na serwerze zawsze jest obiektem Player klienta, który go wzywa, a następnie dodatkowe parametry obserwować.

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

Następujący Script łączy menedżera zdarzeń z OnServerEvent który tworzy nowe Part na serwerze.Następnie towarzyszący LocalScript wezwuje FireServer() na instancji RemoteEvent z pożądanym Color i Position dla części.

Połączenie zdarzenia - Skrypt

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Workspace = game:GetService("Workspace")
-- Zdobądź odniesienie do zdalnej instancji instancja
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
-- Połącz funkcję z wydarzeniem
remoteEvent.OnServerEvent:Connect(onCreatePart)
Strzelanie zdarzeń - Lokalny skrypt

local ReplicatedStorage = game:GetService("ReplicatedStorage")
-- Zdobądź odniesienie do zdalnej instancji instancja
local remoteEvent = ReplicatedStorage:FindFirstChildOfClass("RemoteEvent")
-- Wystrzel zdarzenie zdalne i przekaż dodatkowe argumenty
remoteEvent:FireServer(Color3.fromRGB(255, 0, 0), Vector3.new(0, 25, -20))

Serwer → klient

Możesz użyć , aby uruchomić wydarzenie na klientzie poprzez wezwanie metody na .Pierwszy argument dla jest obiektem klienta, na który chcesz odpowiedzieć na wydarzenie, a dodatkowe argumenty przekazane są do klienta z pewnymi ograniczeniami .Zauważ, że menadżer zdarzeń nie musi zawierać obiektu Player jako pierwszego argumentu, ponieważ możesz określić gracza na klientzie za pomocą Players.LocalPlayer .

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

Następujący LocalScript łączy menadżera zdarzeń z wydarzeniem OnClientEvent .Towarzyszący Script wysłuchuje wtedy nadchodzących graczy na serwer i dzwoni FireClient() dla każdego z dowolnymi danymi.

Połączenie z wydarzeniem - LocalScript

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")
-- Zdobądź odniesienie do zdalnej instancji instancja
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
-- Połącz funkcję z wydarzeniem
remoteEvent.OnClientEvent:Connect(onNotifyPlayer)
Strzelanie zdarzeń - Skrypt

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")
-- Zdobądź odniesienie do zdalnej instancji instancja
local remoteEvent = ReplicatedStorage:FindFirstChildOfClass("RemoteEvent")
-- Słuchaj nadchodzących graczy i wysyłaj zdalne wydarzenie do każdego
local function onPlayerAdded(player)
print("[Server] Firing event to player", player.Name)
remoteEvent:FireClient(player, Players.MaxPlayers, Players.RespawnTime)
end
Players.PlayerAdded:Connect(onPlayerAdded)

Serwer → wszystkie klienty

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

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

Następujący LocalScript łączy menedżera zdarzeń z wydarzeniem OnClientEvent, które wyświetla czas odliczania pozostały.Następnie towarzyszący Script wzywa FireAllClients() w pętli co sekundę, aby uruchomić RemoteEvent dla wszystkich klientów.

Połączenie z wydarzeniem - LocalScript

local ReplicatedStorage = game:GetService("ReplicatedStorage")
-- Zdobądź odniesienie do zdalnej instancji instancja
local remoteEvent = ReplicatedStorage:FindFirstChildOfClass("RemoteEvent")
local function onTimerUpdate(seconds)
print(seconds)
end
-- Połącz funkcję z wydarzeniem
remoteEvent.OnClientEvent:Connect(onTimerUpdate)
Strzelanie zdarzeń - Skrypt

local ReplicatedStorage = game:GetService("ReplicatedStorage")
-- Zdobądź odniesienie do zdalnej instancji instancja
local remoteEvent = ReplicatedStorage:FindFirstChildOfClass("RemoteEvent")
local countdown = 5
-- Strzelaj zdarzenie zdalne co sekundę, aż czas wygaśnie
for timeRemaining = -1, countdown do
remoteEvent:FireAllClients(countdown - timeRemaining)
task.wait(1)
end

Zdalne wezwania powrotne

Przedmiot RemoteFunction ułatwia synchroniczną, dwukierunkową komunikację na granicy klient-serwer.Wysyłający funkcji zdalnej będzie czekać, dopóki nie otrzyma odpowiedzi od odbiorca.

Aby utworzyć nowy RemoteFunction za pomocą okna Explorer w Studio:

  1. Najedź na pojemnik, do którego chcesz wstawić RemoteFunction.Aby zapewnić dostęp zarówno serwera, jak i klienta, musi znajdować się w miejscu, w którym obie strony mogą go zobaczyć, takim jak ReplicatedStorage, choć w niektórych przypadkach właściwe jest przechowywanie go w Workspace lub wewnątrz Tool.
  2. Kliknij przycisk , który pojawia się po prawej stronie nazwy kontenera i wstaw instancję RemoteFunction .
  3. Zmień nazwę instancji, aby opisać jej cel.

Po utworzeniu RemoteFunction może ułatwić 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ć , aby wezwać funkcję na serwerze poprzez wezwanie metody na .W przeciwieństwie do zdarzenia zdalnego remote, które wywołuje LocalScript, które wzywa RemoteFunction aż do powrotu wezwania.Argumenty, które przekazujesz do InvokeServer() przekazują się do powrotu OnServerInvoke z pewnymi ograniczeniami RemoteFunction z .Zauważ, że jeśli zdefiniujesz wiele powrotów do tego samego RemoteFunction, tylko ostatnia definicja zostanie wykonana.

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

Następująca Script określa funkcję powrotną za pomocą OnServerInvoke i zwraca żądaną Part poprzez jej wartość return.Następnie towarzyszący LocalScript wzywa InvokeServer() z dodatkowymi argumentami określającymi pożądaną część koloru i pozycję.

Połączenie powrotne - Skrypt

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Workspace = game:GetService("Workspace")
-- Zdobądź odniesienie do instancji zdalnej funkcji
local remoteFunction = ReplicatedStorage:FindFirstChildOfClass("RemoteFunction")
-- Funkcja powrotu
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
-- Ustaw funkcję jako powrót funkcji zdalnej
remoteFunction.OnServerInvoke = createPart
Wezwanie wydarzenia - LocalScript

local ReplicatedStorage = game:GetService("ReplicatedStorage")
-- Zdobądź odniesienie do instancji zdalnej funkcji
local remoteFunction = ReplicatedStorage:FindFirstChildOfClass("RemoteFunction")
-- Przekaż kolor i pozycję podczas wzywania powrotu
local newPart = remoteFunction:InvokeServer(Color3.fromRGB(255, 0, 0), Vector3.new(0, 25, -20))
-- Wyświetl odwołanie do zwróconej części
print("The server created the requested part:", newPart)

Serwer → klient → serwer

Możesz użyć Script , aby wezwać funkcję na klientzie, wywołując metodę InvokeClient() na RemoteFunction, ale ma poważne ryzyko, jak następuje:

  • Jeśli klient rzuca błąd, serwer również rzuca błąd.
  • Jeśli klient odłączy się, gdy jest wzywany, InvokeClient() wyśle błąd.
  • Jeśli klient nie zwraca wartości, serwer zachowuje się na zawsze.

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

Ograniczenia argumentów

Kiedy wystrzelasz RemoteEvent lub wzywasz RemoteFunction, przekazujesz wszystkie argumenty, które przekazujesz z wydarzeniem lub do funkcji powrotu.Wszelki rodzaj obiektu Roblox, takiego jak Enum , Instance lub inne, może zostać przekazany, a także typy Luau, takie jak liczby, ciągi i booliany, choć powinieneś uważnie przeanalizować następujące ograniczenia.

Nie stringowe indeksy

Jeśli którekolwiek indeksy z przekazanego stołu są typami nietekstowymi, takimi jak Instance , dane użytkownika lub funkcja, Roblox automatycznie konwertuje te indeksy na struny.

Połączenie z wydarzeniem - LocalScript

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local remoteEvent = ReplicatedStorage:FindFirstChildOfClass("RemoteEvent")
local function onEventFire(passedTable)
for k, v in passedTable do
print(typeof(k)) --> ciąg
end
end
-- Połącz funkcję z wydarzeniem
remoteEvent.OnClientEvent:Connect(onEventFire)
Strzelanie zdarzeń - Skrypt

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

Przekazane funkcje

Funkcje włączone jako argumenty dla RemoteEvent lub RemoteFunction zostaną nie skopiowane na granicy klient-serwer, co uniemożliwia przekazywanie funkcji zdalnie.Zamiast tego wynikowy argument po stronie odbiorczej będzie nil .

Połączenie z wydarzeniem - LocalScript

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local remoteEvent = ReplicatedStorage:FindFirstChildOfClass("RemoteEvent")
local function onClientEvent(func)
print(func) --> nil
end
remoteEvent.OnClientEvent:Connect(onClientEvent)
Strzelanie zdarzeń - Skrypt

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local remoteEvent = ReplicatedStorage:FindFirstChildOfClass("RemoteEvent")
local function testFunction()
print("Hello world!")
end
-- Wyzwól zdarzenie zdalne z funkcją jako argumentem
remoteEvent:FireAllClients(testFunction)

Indeksowanie tabel

Jeśli przekazujesz tabelę danych, nie przekazuj mieszanej tabeli liczbowych i kluczy tekstowych.Zamiast tego przekaż tabelę, która składa się w całości z par klucz-wartość (słownik) lub w całości z indeksów liczbowych.

Połączenie zdarzenia - Skrypt

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
--> Nazwa postaci = Diva Dragonslayer
--> CharClass = Szkodnik
end
end
-- Połącz funkcję z wydarzeniem
remoteEvent.OnServerEvent:Connect(onEventFire)
Strzelanie zdarzeń - Lokalny skrypt

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local remoteEvent = ReplicatedStorage:FindFirstChildOfClass("RemoteEvent")
-- Tablica numerowo indeksowana
local inventoryData = {
"Sword", "Bow"
}
-- Tabela słownika
local characterData = {
CharName = "Diva Dragonslayer",
CharClass = "Rogue"
}
remoteEvent:FireServer(inventoryData)
remoteEvent:FireServer(characterData)

Tożsamości tabel

Tabele przekazywane jako argumenty do zdalnych wydarzeń/ callbacków są kopiowane, co oznacza, że nie będą dokładnie równoważne tym dostarczonym podczas uruchamiania wydarzenia lub wzywania powrotu.Nie będą również tabele zwracane do invokera dokładnie odpowiadały tym dostarczonym.Możesz to pokazać, uruchamiając następujący skrypt na RemoteFunction i obserwując, jak różnią się identyfikatory tabeli.

Połączenie powrotne - Skrypt

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local remoteFunction = ReplicatedStorage:FindFirstChildOfClass("RemoteFunction")
-- Funkcja powrotu
local function returnTable(player, passedTable)
-- Wyświetlanie tożsamości tablicy wyników przy wezwaniu
print(tostring(passedTable)) --> stół: 0x48eb7aead27563d9
return passedTable
end
-- Ustaw funkcję jako powrót funkcji zdalnej
remoteFunction.OnServerInvoke = returnTable
Wezwanie wydarzenia - LocalScript

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local remoteFunction = ReplicatedStorage:FindFirstChildOfClass("RemoteFunction")
local inventoryData = {
"Sword", "Bow"
}
-- Wyświetl oryginalną tożsamość tablicy
print(tostring(inventoryData)) --> stół: 0x059bcdbb2b576549
local invokeReturn = remoteFunction:InvokeServer(inventoryData)
-- Wyświetlanie tożsamości tabeli po powrocie
print(tostring(invokeReturn)) --> table: 0x9fcae7919563a0e9

Metatabelki

Jeśli stół ma metatable, wszystkie informacje metatable są utracone w transferze.W następnym przykładzie kodu właściwość NumWheels jest częścią Car metatable.Kiedy serwer otrzymuje poniższą tabelę, tabela ma właściwość , ale nie ma właściwości .

Połączenie zdarzenia - Skrypt

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local remoteEvent = ReplicatedStorage:FindFirstChildOfClass("RemoteEvent")
local function onEvent(player, param)
print(param) --> { ["Nazwa"] = "MyTruck"}
end
-- Połącz funkcję z wydarzeniem
remoteEvent.OnServerEvent:Connect(onEvent)
Strzelanie zdarzeń - Lokalny skrypt

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)
-- Wydarzenie ognia z tabelą, w której znajduje się metatable
remoteEvent:FireServer(truck)

Instancje niezareplikowane

Jeśli RemoteEvent lub RemoteFunction przekazuje wartość widoczną tylko dla nadawcy, Roblox nie replikuje jej poza granicą klienta-serwera i przekazuje nil zamiast wartości.Na przykład, jeśli Script przechodzi potomek ServerStorage , klient słuchający wydarzenia otrzyma wartość nil ponieważ ten obiekt nie jest replikowany dla klienta.

Strzelanie zdarzeń - Skrypt

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local ServerStorage = game:GetService("ServerStorage")
local Players = game:GetService("Players")
local remoteEvent = ReplicatedStorage:FindFirstChildOfClass("RemoteEvent")
-- Zostanie otrzymany jako "null", ponieważ klient nie może uzyskać 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 utworzysz część w LocalScript i spróbujesz przekazać ją do Script, serwer zobaczy nil ponieważ część nie jest replikowalna dla serwera.

Strzelanie zdarzeń - Lokalny skrypt

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Workspace = game:GetService("Workspace")
local remoteEvent = ReplicatedStorage:FindFirstChildOfClass("RemoteEvent")
-- Zostanie otrzymany jako "null", ponieważ serwer nie wie o tej części
local clientPart = Instance.new("Part")
clientPart.Parent = Workspace
remoteEvent:FireServer(clientPart)