Doświadczenia Roblox są wieloosobowe domyślnie, więc wszystkie doświadczenia zasadniczo komunikują się między serwerem a połączonymi klientami graczy. W najprostszym przypadku, gdy gracze przesuwają swoje postacie, niektóre Humanoid właściwości, takie jak stan, są komunikowane z serwerem, który przekazuje tę informację do innych połączonych klientów.
Zdalne wydarzenia i wezwania pozwalają na komunikację pomiędzy granicą klienta-serwera:
- RemoteEvents włącz jednokierunkową komunikację (wysyłanie prośby i nie dostarczanie dla odpowiedzi).
- UnreliableRemoteEvents włącz jednokierunkową komunikację dla danych, które się szybko zmieniają lub nie są krytyczne dla stanu gry. Te wydarzenia wymieniają i zapewniają wiarygodność dla poprawy wykonywaniesieci.
- RemoteFunctions włącz dwukolorową komunikację (wysyłanie prośby i oczekiwanie na otrzymanie odpowiedzi od odbiorca).
W przeciwieństwie do powiązanych wydarzeń, które mają ograniczoną funkcjonalność, przypadki użycia dla zdalnych wydarzeń i funkcji są zbyt liczne, aby je wymienić:
- GAMEPLAY - Podstawowe rozgrywka, takie jak osiągnięcie gracza końca poziomu, może wymagać zdalnego zdarzenia. Skrypt klienta informuje serwer i serwerowe skrypty zresetują pozycję gracza.
- Zweryfikacja serwera - Jeśli gracz próbuje wypić eliksir, czy on naprawdę ma ten eliksir? Aby zagwarantować uczciwość, serwer musi być źródłem prawdy dla doświadczenia. Skrypt klienta może użyć zdalnego wydarzenia, aby powiadomić serwer, że gracz wypija eliksir, a następnie serwer może zdecydować,
- Aktualizacje interfejsu użytkownika - gdy stan gry się zmienia, serwerowe skrypty mogą używać zdarzeń zdalnych, aby poinformować klientów o zmianach wyników, celów itp.
- Wнутri-ezperyjne zakupy rynkowe - Dla przykładowej implementacji używającej zasadniczo funkcji zdalnych, zobacz Wymagające zakupy subskrypcji .
Szybki przewodnik
Poniższe tabelary służą jako szybki przewodnik dla tego, jak używać RemoteEvents i RemoteFunctions, aby komunikować się między klientem a serwerem.
Klient → Serwer | >|
---|---|
Klient | RemoteEvent:FireServer(args) |
Serwer | RemoteEvent.OnServerEvent:Connect(function(player, args)) |
Serwer → Klient | |
Serwer | RemoteEvent:FireClient(player, args) |
Klient | RemoteEvent.OnClientEvent:Connect(function(args)) |
Serwer → Wszystkie Klienty | >|
Serwer | RemoteEvent:FireAllClients(args) |
Klient | RemoteEvent.OnClientEvent:Connect(function(args)) |
Wydarzenia zdalne
Obiekt RemoteEvent ułatwia bezasynchroniczną komunikację jednokierunkową między klientem a serwerem bez konieczności dostarczania odpowiedzi.
Aby utworzyć nowy RemoteEvent poprzez okno Explorer w Studio:
- Przytrzymajте myszkę na kontenerze, do którego chcesz wstawić RemoteEvent. Aby zagwarantować dostęp zarówno dla serwera, jak i klienta, musi on znajdować się w miejscu, w którym obie strony mogą go zobaczyć, takim jak ReplicatedStorage , choć w niektórych przypadk
- Kliknij przycisk ⊕ , który pojawia się po prawej stronie imienia kontenera i wpisz instancję RemoteEvent .
- Zmień nazwę instancji, aby opisać jej cel.
Kiedy stworzysz RemoteEvent, możesz ułatwić jednokierunkową komunikację od klienta do serwera, z serwera do klienta lub z 2>serwera do wszystkich klientów2>.
Klient → Serwer
Możesz użyć LocalScript , aby wywołać wydarzenie na serwerze poprzez wezwanie metody Class.RemoteEvent:FireServer()|FireServer() na <
Klient | RemoteEvent:FireServer(args) |
Serwer | RemoteEvent.OnServerEvent:Connect(function(player, args)) |
Poniższy Script połącza węzłowy handlerewentów z OnServerEvent, który tworzy nowy
Połączenie wątku - Skrypt
local ReplicatedStorage = game:GetService("ReplicatedStorage")
-- Zdobądź odniesienie do instancji zdarzenia 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)
Wydarzenie - Lokalny Skrypt
local ReplicatedStorage = game:GetService("ReplicatedStorage")-- Zdobądź odniesienie do instancji zdarzenia instancjalocal remoteEvent = ReplicatedStorage:FindFirstChildOfClass("RemoteEvent")-- Wykonaj zdalne wydarzenie i przekaż dodatkowe argumentyremoteEvent:FireServer(Color3.fromRGB(255, 0, 0), Vector3.new(0, 25, -20))
Serwer → Klient
Możesz użyć Script , aby
Serwer | RemoteEvent:FireClient(player, args) |
Klient | RemoteEvent.OnClientEvent:Connect(function(args)) |
Następny LocalScript połączy wrażliwy na wydarzenia OnClientEvent z wydarzeniem Script. Załączający 2>Class.Script2> słucha wtedy przychodzących graczy na serwer i wzywa 5>Class.RemoteEvent:FireClient()|FireClient()5> dla każdej z dowolnych dany
Połączenie wątku - Lokalny Skrypt
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")
-- Zdobądź odniesienie do instancji zdarzenia 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)
Wydarzenie - Skrypt
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")
-- Zdobądź odniesienie do instancji zdarzenia instancja
local remoteEvent = ReplicatedStorage:FindFirstChildOfClass("RemoteEvent")
-- Słuchaj zarządzaj zdalnymi wydarzeniami do każdego przychodzącego gracza
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 zainicjować wydarzenie na wszystkich klientach, wzywając metodę Class.RemoteEvent:FireAllClients()|FireAllClients()</
Serwer | RemoteEvent:FireAllClients(args) |
Klient | RemoteEvent.OnClientEvent:Connect(function(args)) |
Poniższy LocalScript połączyć z wydarzeniem OnClientEvent, które wyświetla pozostały czas odliczania. Z kolei Script wzywa co sekundę 2>Class.RemoteEvent:FireAllClients()|FireAllClients()2> w pęt
Połączenie wątku - Lokalny Skrypt
local ReplicatedStorage = game:GetService("ReplicatedStorage")
-- Zdobądź odniesienie do instancji zdarzenia instancja
local remoteEvent = ReplicatedStorage:FindFirstChildOfClass("RemoteEvent")
local function onTimerUpdate(seconds)
print(seconds)
end
-- Połącz funkcję z wydarzeniem
remoteEvent.OnClientEvent:Connect(onTimerUpdate)
Wydarzenie - Skrypt
local ReplicatedStorage = game:GetService("ReplicatedStorage")-- Zdobądź odniesienie do instancji zdarzenia instancjalocal remoteEvent = ReplicatedStorage:FindFirstChildOfClass("RemoteEvent")local countdown = 5-- Wykonuj zdalne wydarzenie co druga sekunda, aż czas wygasafor timeRemaining = -1, countdown doremoteEvent:FireAllClients(countdown - timeRemaining)task.wait(1)end
Zwolnij
Obiekt RemoteFunction ułatwia komunikację synchronizowaną dwukolorową między granicą klienta-serwera. Wysyłacz funkcji zdalnej będzie wygrywać do czasu otrzymania odpowiedzi od odbiorca.
Aby utworzyć nowy RemoteFunction poprzez okno Explorer w Studio:
- Przytrzymajте myszkę na kontenerze, do którego chcesz wstawić RemoteFunction. Aby zagwarantować dostęp zarówno dla serwera, jak i klienta, musi on znajdować się w miejscu, w którym obie strony mogą go zobaczyć, takim jak ReplicatedStorage , choć w niektórych przypadk
- Kliknij przycisk ⊕ , który pojawia się po prawej stronie imienia kontenera i wpisz instancję RemoteFunction .
- Zmień nazwę instancji, aby opisać jej cel.
Gdy stworzysz RemoteFunction, może ułatwić komunikację dwukolorową między klientem a serwerem lub między serwerem a klientem.
Klient → Serwer → Klient
Możesz użyć LocalScript , aby wejść w posiadanie funkcji na serwer poprzez wezwanie metody Class.RemoteFunction:Execute
Klient | RemoteFunction:InvokeServer(args) |
Serwer | RemoteFunction.OnServerInvoke = function(player, args) |
Poniższy Script definuje funkcję zwrotu poprzez OnServerInvoke i zwraca żądany Part poprzez jego wartość 2>return2>. Następny 5>Class.LocalScript5> wzywa 8>
Callback połączenie - Skrypt
local ReplicatedStorage = game:GetService("ReplicatedStorage")
-- Zdobądź odniesienie do instancji funkcji zdalnej
local remoteFunction = ReplicatedStorage:FindFirstChildOfClass("RemoteFunction")
-- Funkcja zwrotu
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 wzwanie funkcji zdalnej
remoteFunction.OnServerInvoke = createPart
Wyzwanie wydarzenia - Lokalny Skrypt
local ReplicatedStorage = game:GetService("ReplicatedStorage")-- Zdobądź odniesienie do instancji funkcji zdalnejlocal remoteFunction = ReplicatedStorage:FindFirstChildOfClass("RemoteFunction")-- Przekaż kolor i pozycję podczas wzywania funkcjilocal newPart = remoteFunction:InvokeServer(Color3.fromRGB(255, 0, 0), Vector3.new(0, 25, -20))-- Wyświetl odnośnik części zwróconejprint("The server created the requested part:", newPart)
Serwer → Klient → Serwer
Możesz użyć Script , aby wejść na funkcję na klientze, poprzez wezwanie metody Class.RemoteFunction:ExecuteClient()|ExecuteClient() na Class.RemoteFunction, ale ma poważne ryzyko, jak następuje:
- Jeśli klient rzuca błędem, serwer rzuca błędem również.
- Jeśli klient się odłącza podczas uruchamiania, InvokeClient() wyrzuca błąd.
- Jeśli klient nie zwraca wartości, serwer zachowuje na zawsze.
Dla akcji, które nie wymagają dwukolorowych komunikacji, takich jak aktualizacja interfejsu użytkownika, użyj RemoteEvent i komunikuj się z serwera do klienta.
Ograniczenia argumentów
Gdy wyrzucasz RemoteEvent lub wzywasz RemoteFunction, przekazuje wszystkie argumenty, które przekazujesz z wydarzenia lub funkcji zwrotnej. Każdy rodzaj obiektu Roblox, takiego jak Enum , 2>Class.Instance2> lub inne, może być prz
Niezależne wskaźniki
Jeśli którekolwiek indeksy tabeli przepustej są niestrukturalnymi typami, takimi jak Instance , userdata lub 1>funkcja1>, Roblox automatycznie konwertuje te indeksy w strójce.
Połączenie wątku - Lokalny Skrypt
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)
Wydarzenie - Skrypt
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")
local remoteEvent = ReplicatedStorage:FindFirstChildOfClass("RemoteEvent")
-- Słuchaj zarządzaj zdalnymi wydarzeniami do każdego przychodzącego gracza
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, nie będą kopiowane poprzez granicę klient-serwer, uniemożliwiając w ten sposób przesyłanie funkcji zdalnie. Zamiast tego wynik argumentu na stronie odbiorczej będzie 2>nil2>.
Połączenie wątku - Lokalny Skrypt
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local remoteEvent = ReplicatedStorage:FindFirstChildOfClass("RemoteEvent")
local function onClientEvent(func)
print(func) --> zero
end
remoteEvent.OnClientEvent:Connect(onClientEvent)
Wydarzenie - Skrypt
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local remoteEvent = ReplicatedStorage:FindFirstChildOfClass("RemoteEvent")
local function testFunction()
print("Hello world!")
end
-- Zdalne wydarzenie z funkcją jako argument
remoteEvent:FireAllClients(testFunction)
Indeksowanie Tabel
Jeśli przeszesz tabelę danych, nie przeszesz mieszaną tabelę kluczy numerowych i literackich. Zamiast tego przeszesz tabelę, która składa się w całości pary kluczowe (słownik) lub w całości kluczowe indeksy.
Połączenie wątku - 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
--> CharName = Diva Dragonslayer
--> CharClass = Rogue
end
end
-- Połącz funkcję z wydarzeniem
remoteEvent.OnServerEvent:Connect(onEventFire)
Wydarzenie - Lokalny Skrypt
local ReplicatedStorage = game:GetService("ReplicatedStorage")local remoteEvent = ReplicatedStorage:FindFirstChildOfClass("RemoteEvent")-- Liczbowo z索wana tabelalocal inventoryData = {"Sword", "Bow"}-- Tabela słownikalocal characterData = {CharName = "Diva Dragonslayer",CharClass = "Rogue"}remoteEvent:FireServer(inventoryData)remoteEvent:FireServer(characterData)
Tożsamość tabeli
Tabele przesłane jako argumenty do zdalnych wydarzeń/zwrotów klamer są kopiowane, co oznacza, że nie będą dokładnie równoważne z tymi dostarczanymi podczas uruchamiania wydarzenia lub wzywania zwrotu klamer. Nie zostaną one również zwrócone do wskazanego przez wskazującego, co można zrobić poprzez uruchomienie następującego skryptu na RemoteFunction
Callback połączenie - Skrypt
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local remoteFunction = ReplicatedStorage:FindFirstChildOfClass("RemoteFunction")
-- Funkcja zwrotu
local function returnTable(player, passedTable)
-- Wyświetl tożsamość tabeli przy wezwaniu
print(tostring(passedTable)) --> tabela: 0x48eb7aead27563d9
return passedTable
end
-- Ustaw funkcję jako wzwanie funkcji zdalnej
remoteFunction.OnServerInvoke = returnTable
Wyzwanie wydarzenia - Lokalny Skrypt
local ReplicatedStorage = game:GetService("ReplicatedStorage")local remoteFunction = ReplicatedStorage:FindFirstChildOfClass("RemoteFunction")local inventoryData = {"Sword", "Bow"}-- Wyświetl oryginalną tożsamość tabeliprint(tostring(inventoryData)) --> tabela: 0x059bcdbb2b576549local invokeReturn = remoteFunction:InvokeServer(inventoryData)-- Wyświetl tożsamość tabeli przy powrocieprint(tostring(invokeReturn)) --> table: 0x9fcae7919563a0e9
Metatabela
Jeśli tabela ma metabelę, wszystkie informacje o metabeli w przekazie zostaną stracone. W następnym przykładzie kodu właściwość NumWheels jest częścią metabeli Car. Gdy serwer otrzymuje następującą tabelę, właściwość
Połączenie wątku - 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)
Wydarzenie - Lokalny Skrypt
local ReplicatedStorage = game:GetService("ReplicatedStorage")local remoteEvent = ReplicatedStorage:FindFirstChildOfClass("RemoteEvent")local Car = {}Car.NumWheels = 4Car.__index = Carlocal truck = {}truck.Name = "MyTruck"setmetatable(truck, Car)-- Wydarzenie ognia z tabelą zawierającą metabelęremoteEvent:FireServer(truck)
Niezależne instancje
Jeśli RemoteEvent lub RemoteFunction przesyła wartość, która jest widoczna tylko dla nadawcy, Roblox nie replikuje jej na całej granicy klient-serwer i przesyła nil z
Wydarzenie - Skrypt
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local ServerStorage = game:GetService("ServerStorage")
local Players = game:GetService("Players")
local remoteEvent = ReplicatedStorage:FindFirstChildOfClass("RemoteEvent")
-- Zostanie otrzymany jako "nil", 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 stworzysz część w LocalScript i spróbujesz ją przesłać do Script, serwer zobaczy nil, ponieważ część nie jest replikowalna dla serwera.
Wydarzenie - Lokalny Skrypt
local ReplicatedStorage = game:GetService("ReplicatedStorage")local remoteEvent = ReplicatedStorage:FindFirstChildOfClass("RemoteEvent")-- Zostanie otrzymany jako "nil", ponieważ serwer nie wie o tej częścilocal clientPart = Instance.new("Part")clientPart.Parent = workspaceremoteEvent:FireServer(clientPart)