W modelu autorytetu serwera serwer jest jedynym źródłem prawdy dla całego stanu doświadczenia, a klienci są jedynie zaufanymi źródłami do raportowania swoich własnych wejść. Ta architektura jest podstawą netcode'u uczciwego i konkurencyjnego doświadczenia, ponieważ zapobiega całym klasom oszustw, takim jak flyhacks czy speedhacks, nigdy nie ufając klientowi w raportowaniu swojej własnej pozycji lub stanu.
Zalety
W naiwnej systemie z serwerem jako właścicielem, klienci po prostu wysyłaliby swoje wejścia do serwera i wyświetlali wyniki doświadczenia zwracane przez serwer. Choć technicznie poprawne, taki system napotkałby znaczne opóźnienie wejściowe, ponieważ każde działanie gracza musiałoby podróżować do serwera, być przetwarzane i mieć wynik odesłany z powrotem do klienta, zanim mogłoby zostać wyświetlone. W przypadku większości doświadczeń, zwłaszcza tych dynamicznych, opóźnienie z tą podróżą sprawiłoby, że rozgrywka wydawałaby się lagowana, nieodpowiednia i niegrywalna.
W modelu autorytetu serwera Robloxa, opóźnienie jest rekompensowane przez to, że klienci natychmiastowo prognozują skutki swoich wejść, oprócz wysyłania ich do serwera. Na przykład, gdy gracz naciska klawisz, klient nie czeka na odpowiedź serwera; zamiast tego prognozuje kilka klatek na przód od ostatniego znanego stanu serwera. Pozwala to klientowi na natychmiastowe pokazanie wyniku akcji wejściowej, skutecznie ukrywając opóźnienie sieciowe i sprawiając, że doświadczenie wydaje się responsywne.
Czasami klient błędnie prognozuje (misprediction) i, z powodu opóźnienia sieciowego, klient nie będzie wiedział, że popełnił błąd przez kilka klatek. Na przykład:
Gdy wykryty jest błąd w prognozie, klient musi skorygować swoją prognozę w oparciu o autorytatywny stan serwera. Jeśli stan autorytatywny różni się od prognozowanego stanu klienta, klient musi cofnąć się i na nowo zasymulować swoje prognozowane klatki. Ten system prognozowania po stronie klienta, cofnięcia się i na nowo zasymulowania jest znany jako "kompensacja opóźnienia" i pomaga sprawić, że doświadczenia wieloosobowe z autorytetem serwera są płynne i responsywne.
Ustawienia
Model autorytetu serwera wymaga, aby niektóre inne technologie silnika działały poprawnie, dlatego musisz najpierw ustawić następujące właściwości obiektu Workspace w Eksploratorze:
- Workspace.NextGenerationReplication musi być włączone
- Workspace.PlayerScriptsUseInputActionSystem musi być włączone
- Workspace.SignalBehavior musi mieć wartość Deferred
- Workspace.UseFixedSimulation musi być włączone
- Workspace.StreamingEnabled musi być włączone
- Workspace.AuthorityMode musi mieć wartość Server (wszystkie powyższe muszą być ustawione najpierw)
Koncepcje
System autorytetu serwera opiera się na kilku podstawowych koncepcjach, jak niżej.
Prognozowanie klienta
Dzięki prognozowaniu klienta, klient symuluje kilka klatek na przód od ostatniego znanego stanu serwera, aby natychmiast prognozować skutki wejść gracza. To ukrywa opóźnienie wejściowe, ale prognoza może później okazać się błędna (błąd prognozy klienta), co wymaga korekty. Klient stara się symulować wystarczająco daleko na przód od ostatniego znanego autorytatywnego stanu serwera, aby jego wejścia dotarły do serwera w zamierzonym czasie. Liczba klatek, które klient prognozować będzie na przód od znanego stanu serwera, opiera się na opóźnieniu między klientem a serwerem.
Błąd prognozy klienta
Gdy klient otrzymuje autorytatywny stan z serwera, sprawdza ten stan w porównaniu z historycznym zbiorem tego, co prognozował lokalnie w tej klatce. Gdy występuje różnica między tym, co klient prognozował, a tym, co serwer faktycznie zrobił, to jest to błąd prognozy. Błędy prognozy mogą występować z różnych powodów, w tym przesunięcia w opóźnieniu sieciowym, działań innych graczy w sposób, którego klient się nie spodziewał, logika doświadczenia działająca wyłącznie na serwerze itp.
Jeśli stan autorytatywny różni się od prognozowanego stanu klienta, klient musi cofnąć się i na nowo zasymulować.
Cofnięcie się i na nowo zasymulowanie
Gdy klient wykryje błąd prognozy, musi zresetować do autorytatywnego stanu serwera, a następnie na nowo zasymulować, aby wrócić do swojej prognozowanej klatki. Na podstawie opóźnienia sieciowego, klient stara się symulować wystarczająco daleko na przód od ostatniego znanego autorytatywnego stanu serwera, aby jego wejścia dotarły do serwera w zamierzonym czasie.
Podsumowując, klient:
- Otrzymuje autorytatywny stan z serwera i porównuje go z własnym prognozowanym stanem.
- Jeśli prognoza klienta była błędna:
- Klient cofa się do ostatniego znanego autorytatywnego stanu otrzymanego z serwera.
- Klient na nowo symuluje od stanu autorytatywnego do swojego prognozowanego stanu, ponownie stosując wszelkie lokalne wejścia.
Implementacja
Własność sieciowa i prognozowanie
W modelu autorytetu serwera możesz zachować podstawowe obiekty rozgrywki jako własność serwera, nie ponosząc kosztów opóźnienia wejściowego związanych z byciem właścicielem serwera. Rzeczy takie jak samochody, postacie graczy czy inne obiekty krytyczne dla rozgrywki mogą pozostać jako własność serwera, nawet gdy wchodzą w interakcję z innymi graczami.
Domyślnie Roblox automatycznie prognozuje właściwości z dostępem do symulacji blisko lokalnego gracza Character, ale jeśli chcesz mieć większą kontrolę, możesz wyraźnie wymusić prognozowanie instancji włączone lub wyłączone za pomocą RunService:SetPredictionMode().
Synchronizacja symulacji
W modelu autorytetu serwera zarówno klient, jak i serwer muszą uruchomić podstawową symulację, a symulacja klienta musi być w stanie cofnąć się i na nowo zasymulować, gdy występuje błąd prognozy. Aby to umożliwić, napisz swoją podstawową logikę wewnątrz funkcji związanych przez RunService:BindToSimulation() w ModuleScript, który jest inicjowany zarówno po stronie klienta, jak i serwera.

Podczas na nowo zasymulowania, Roblox ponownie uruchomi funkcje związane z symulacją przez BindToSimulation(). Przetwarzanie wejść graczy, interakcja z synchronizowanymi obiektami fizycznymi i aktualizowanie stanu podstawowego doświadczenia powinny znajdować się w tych związanych funkcjach.
ModuleScript o nazwie Symulacja w ReplicatedStorage:
Symulacja
local RunService = game:GetService("RunService")
local Players = game:GetService("Players")
local Symulacja = {}
Symulacja.Inicjalizuj = function()
RunService:BindToSimulation(function(deltaTime)
-- Odczytaj wejścia graczy
-- Zaktualizuj stan doświadczenia
end)
end
return Symulacja
Synchronizacja stanu z atrybutami
Roblox automatycznie synchronizuje wszystkie właściwości z dostępem do symulacji na prognozowanych instancjach. Dla danych niestandardowych, atrybuty są głównym sposobem synchronizacji instancji oznaczonych jako prognozowane; na takich instancjach wszelkie różnice w wartościach atrybutów między źródłem prawdy serwera a prognozami klienta wywołają pełne cofnięcie i na nowo zasymulowanie.
Limity atrybutów
Aby atrybut mógł być replikowany, musi spełniać wszystkie następujące kryteria:
- Jest jednym z pierwszych 64 atrybutów na swoim Instance.
- Jego nazwa zawiera co najwyżej 50 znaków.
- Jeśli atrybut jest typu string, jego wartość zawiera co najwyżej 50 znaków.
Dostęp do symulacji
Wiele właściwości i metod w odniesieniu do API silnika zawiera etykietę Dostęp do symulacji, na przykład BasePart.CFrame. Właściwości z tą etykietą będą prognozowane przez system autorytetu serwera. Dodatkowo, tylko właściwości i metody z tą etykietą mogą być dostępne wewnątrz funkcji powiązanych przez RunService:BindToSimulation().
Akcje wejściowe
W doświadczeniach z autorytetem serwera, głównym sposobem, w jaki klient może wpływać na stan doświadczenia, jest System Akcji Wejściowych. Te wejścia są wysyłane do serwera i są powtarzane podczas na nowo zasymulowania na kliencie. W związku z tym, InputActions powinny być używane dla wszystkich wejść, które wpływają na podstawową symulację i powinny być sprawdzane pod kątem poprawności przed przetworzeniem.
Zauważ, że InputContexts musi być potomkiem Player, aby silnik wiedział, kto ma własność nad InputContext. Jednym z podejść jest dodanie twoich InputContexts do folderu pod ReplicatedStorage i użycie Script pod ServerScriptService, aby sklonować InputContexts dla każdego gracza:

InputSetup
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local InputsFolder = ReplicatedStorage:WaitForChild("Inputs")
local function onPlayerAdded(player)
local clone = InputsFolder:Clone()
clone.Parent = player
end
Players.PlayerAdded:Connect(onPlayerAdded)
for _, player in Players:GetPlayers() do
onPlayerAdded(player)
end
Używając tego wzorca, możesz odczytać InputActions dla wszystkich graczy w RunService:BindToSimulation() zarówno po stronie klienta, jak i serwera, aby otrzymywać te same dane dla danej klatki i zapisywać poprzednie wejście klatki w atrybucie, na przykład, aby wywołać bieg postaci, gdy wywołana jest akcja wejściowa RunAction.
Zauważ, że jeśli potrzebujesz wprowadzić niestandardowe dane do Systemu Akcji Wejściowych, powinieneś użyć funkcji podłączonej do RunService.RenderStepped lub RunService:BindToRenderStep(), a nie RunService:BindToSimulation(). Uruchomienie InputAction w BindToSimulation() może spowodować, że klienci będą produkować niepoprawne wyniki podczas na nowo zasymulowania.
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local Workspace = game:GetService("Workspace")
RunService:BindToRenderStep("CameraInput", Enum.RenderPriority.Last.Value, function()
-- Wysłanie wektora do przodu kamery klienta do serwera przez InputAction
local cameraForwardInputAction = Players.LocalPlayer.PlayContext.CameraForward
local cameraForwardVector = Workspace.CurrentCamera.CFrame.LookVector
cameraForwardInputAction:Fire(cameraForwardVector)
end)
Zdarzenia zdalne
Zdarzenia zdalne mogą być nadal używane w modelu autorytetu serwera, aby ułatwić dyskretną komunikację między klientem a serwerem. Na przykład serwery mogą używać zdarzeń zdalnych do rozpowszechniania danych o punktach zdobytych przez graczy lub podnoszeniu obiektów, a klienci mogą używać zdarzeń zdalnych jako alternatywnego API do wysyłania wejść do serwera, takich jak naciśnięcia przycisków lub dotykanie obiektów w świat 3D.
Animacje, dźwięki i efekty
Efekty po stronie klienta, takie jak animacje i dźwięki, muszą być pisane w świadomości, że symulacja klienta jest jedynie prognozą autorytatywnego stanu serwera. BindToSimulation() ogranicza, jakie właściwości i metody mogą być wywoływane wewnątrz związanych funkcji, aby pomóc w pisaniu tylko do zsynchronizowanego stanu symulacji. Pokazywanie wyników tej symulacji, wywoływanie efektów i dźwięków itp. powinno być realizowane w osobnej funkcji połączonej z RenderStepped, która odczytuje wyniki symulacji i wywołuje pożądane efekty.
Dalsze wskazówki dotyczące renderowania prognozowanej symulacji są omówione w przewodniku zaawansowanych technik.
Przykładowe projekty
Oprócz tej dokumentacji, następujące szablony mogą pomóc Ci zacząć:


