Model autorytetu serwera

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

W modelu autorytetu serwera serwer jest jedynym źródłem prawdy dla całego stanu gry, a klienci są jedynie zaufani do zgłaszania swoich własnych wejść. Ta architektura stanowi podstawę netcode'u sprawiedliwej, konkurencyjnej gry, ponieważ zapobiega całym klasom oszustw, takim jak flyhacks czy speedhacks, nigdy nie ufając klientowi w zgłaszaniu swojej własnej pozycji lub stanu.

Zalety

W naiwnej systemie własności serwera klienci po prostu wysyłaliby swoje wejścia do serwera i wyświetlali wyniki gry przesyłane z powrotem przez serwer. Choć technicznie poprawne, taki system napotkałby znaczną latencję wejściową, ponieważ każda akcja gracza musiałaby podróżować do serwera, być przetwarzana, a wynik wysyłany z powrotem do klienta, zanim mogłaby być wyświetlona. W przypadku większości gier, szczególnie tych szybkich, opóźnienie w obiegu spowodowałoby, że rozgrywka wydawałaby się opóźniona, nieodpowiednia i niegrywalna.

W modelu autorytetu serwera Roblox latencja jest kompensowana przez to, że klienci natychmiastowo przewidują efekty swoich wejść, oprócz wysyłania ich do serwera. Na przykład, gdy gracz naciska klawisz, klient nie czeka na odpowiedź serwera; zamiast tego przewiduje kilka klatek do przodu od ostatniego znanego stanu serwera. To pozwala klientowi natychmiast pokazać wynik akcji wejściowej, skutecznie ukrywając latencję sieciową i sprawiając, że gra wydaje się responsywna.

Czasami klient może źle przewidzieć (misprediction), a z powodu latencji sieciowej klient nie będzie wiedział, że popełnił błąd przez kilka klatek. Na przykład:

Gdy wykryta zostanie błędna prognoza, klient musi skorygować swoje przewidywanie na podstawie autorytatywnego stanu serwera. Jeśli stan autorytatywny różni się od przewidywanego stanu klienta, klient musi cofnąć się i ponownie symulować swoje przewidywane klatki. Ten system przewidywania po stronie klienta, cofania i ponownej symulacji jest znany jako "kompensacja latencji" i pomaga sprawić, że wieloosobowe gry oparte na autorytecie serwera wydają się płynne i responsywne.

Konfiguracja

Model autorytetu serwera wymaga, aby pewne inne technologie silnika działały poprawnie. Potwierdź następujące ustawienia właściwości na obiekcie Workspace w Eksploratorze:

  1. Workspace.AuthorityMode musi być Server (ustawienie to automatycznie ustawia następujące pięć).
  2. Workspace.UseFixedSimulation musi być włączone.
  3. Workspace.StreamingEnabled musi być włączone.

Koncepcje

System autorytetu serwera działa na kilku podstawowych koncepcjach, jak poniżej.

Przewidywanie klienta

Dzięki przewidywaniu klienta klient symuluje kilka klatek do przodu od ostatniego znanego stanu serwera, aby natychmiast przewidzieć efekty wejść gracza. To ukrywa latencję wejściową, ale przewidywanie może później okazać się błędne (błędne przewidywanie) i wymagać korekty. Klient stara się symulować wystarczająco daleko do przodu od ostatniego znanego autorytatywnego stanu serwera, aby jego wejścia dotarły do serwera w zamierzonym czasie. Liczba klatek, które klient przewidzi do przodu od znanego stanu serwera, opiera się na latencji między klientem a serwerem.

Błędne przewidywanie klienta

Gdy klient otrzymuje autorytatywny stan z serwera, sprawdza ten stan w porównaniu do historycznego zapisu tego, co przewidział lokalnie dla tej klatki. Gdy występuje różnica między tym, co klient przewidział, a tym, co serwer faktycznie zrobił, jest to błędne przewidywanie. Błędne przewidywania mogą wystąpić z kilku powodów, w tym zmiany latencji sieciowej, działania innych graczy, które klient nie przewidział, logika gry działająca wyłącznie na serwerze itp.

Jeśli stan autorytatywny różni się od przewidywanego stanu klienta, klient musi cofnąć się i ponownie symulować.

Cofanie i ponowna symulacja

Gdy klient wykryje błędne przewidywanie, musi zresetować się do autorytatywnego stanu serwera, a następnie ponownie symulować, aby wrócić do swojej przewidywanej klatki. Na podstawie latencji sieciowej klient stara się symulować wystarczająco daleko do przodu od ostatniego znanego autorytatywnego stanu serwera, aby jego wejścia dotarły do serwera w zamierzonym czasie.

Na powyższym diagramie klient symuluje 2 klatki do przodu od serwera. Wysyła swoje wejścia dla klatki 3, które docierają do zamierzonej klatki (3) na serwerze. Serwer wysyła autorytatywny stan dla klatki 3, a klient otrzymuje go w klatce 7. Klient odkrywa, że błędnie przewidział klatkę 3, więc resetuje się do klatki 3 serwera i ponownie symuluje klatki 4, 5 i 6, zanim zasymuluje klatkę 7. Gracze mogą zauważyć zauważalny artefakt sieciowy, taki jak nagłe ruchy.

Podsumowując, klient:

  1. Otrzymuje autorytatywny stan z serwera i porównuje go z własnym przewidywanym stanem.
  2. Jeśli przewidywanie klienta było błędne:
    1. Klient cofa się do ostatniego znanego autorytatywnego stanu otrzymanego z serwera.
    2. Klient ponownie symuluje od stanu autorytatywnego do swojego przewidywanego stanu, ponownie stosując wszelkie lokalne wejścia.

Implementacja

Własność sieciowa i przewidywanie

W modelu autorytetu serwera możesz utrzymać podstawowe obiekty rozgrywki w posiadaniu serwera, nie ponosząc kosztów latencji wejściowej, które normalnie są związane z własnością serwera. Rzeczy takie jak samochody, postacie graczy czy inne obiekty krytyczne dla rozgrywki mogą pozostać w posiadaniu serwera, nawet gdy wchodzą w interakcje z innymi graczami.

Domyślnie Roblox automatycznie przewiduje właściwości z dostępem do symulacji w pobliżu lokalnego gracza Character, ale jeśli chcesz mieć bardziej szczegółową kontrolę, możesz wymusić przewidywanie instancji włączone lub wyłączone za pomocą RunService:SetPredictionMode().

Automatyczne przewidywanie dotyczy całych zespołów fizycznych, a nie pojedynczych instancji. Gdy klient przewiduje część, przewiduje również każdą część, która jest fizycznie z nią połączona przez spawy, stawy lub ograniczenia, wraz z rodzicem Model tych części i wszelkimi Humanoid wewnątrz tego modelu. Na przykład:

  • Model miecza, który jest spawany do przewidywanej postaci, staje się częścią zespołu postaci, więc jest przewidywany automatycznie.
  • Model, który jest rodzicem postaci, ale nie jest fizycznie z nią połączony, jest osobnym zespołem. Jest przewidywany tylko wtedy, gdy znajduje się w promieniu symulacji klienta lub jeśli wymusisz przewidywanie za pomocą RunService:SetPredictionMode().

Aby sprawdzić, czy konkretna instancja jest obecnie przewidywana, wywołaj RunService:GetPredictionStatus() z klienta.

Synchronizacja symulacji

W modelu autorytetu serwera klient i serwer muszą obaj uruchamiać podstawową symulację, a symulacja klienta musi być w stanie cofnąć się i ponownie symulować, gdy występuje błędne przewidywanie. Aby to umożliwić, napisz swoją logikę podstawową wewnątrz funkcji powiązanych przez RunService:BindToSimulation() w ModuleScript, który jest inicjowany zarówno na kliencie, jak i serwerze.

Ustawienia autorytetu serwera

Podczas ponownej symulacji Roblox ponownie uruchomi funkcje powiązane z symulacją za pomocą BindToSimulation(). Przetwarzanie wejść graczy, interakcja z synchronizowanymi obiektami fizycznymi i aktualizacja podstawowego stanu gry powinny odbywać się wewnątrz tych powiązanych funkcji.

Użyj time() do wszelkiej logiki opartej na czasie wewnątrz powiązanej funkcji symulacji, takiej jak prowadzenie prędkości animacji lub oscylowanie wartości w czasie. Gdy Workspace.AuthorityMode jest ustawiony na Enum.AuthorityMode.Server, time() jest synchronizowane między klientem a serwerem i używa stałego kroku czasu symulacji. Podczas ponownej symulacji cofa się do autorytatywnej klatki i postępuje, gdy klient odtwarza klatki, więc zwraca spójną wartość za każdym razem, gdy klatka jest symulowana.

ModuleScript nazwany Symulacja w ReplicatedStorage:

Symulacja
local RunService = game:GetService("RunService")
local Players = game:GetService("Players")
local Symulacja = {}
Symulacja.Initialize = function()
RunService:BindToSimulation(function(deltaTime)
-- Odczytaj wejścia graczy
-- Zaktualizuj stan gry
end)
end
return Symulacja

Synchronizacja stanu z atrybutami

Roblox automatycznie synchronizuje wszystkie właściwości z dostępem do symulacji na przewidywanych instancjach. Dla danych niestandardowych, atrybuty są głównym sposobem synchronizacji instancji oznaczonych jako przewidywane; w przypadku takich instancji wszelkie niezgodności w wartościach atrybutów między źródłem prawdy serwera a przewidywaniem klienta spowodują pełne cofnięcie i ponowną symulację.

Ograniczenia atrybutów

Aby atrybut mógł być replikowany, musi spełniać wszystkie poniższe kryteria:

  • Jest jednym z pierwszych 64 atrybutów na swoim Instance.
  • Jego nazwa zawiera maksymalnie 50 znaków.
  • Jeśli jest atrybutem typu string, jego wartość zawiera maksymalnie 50 znaków.

Dostęp do symulacji

Wiele właściwości i metod w dokumentacji API silnika zawiera etykietę Dostęp do symulacji, na przykład BasePart.CFrame. Właściwości z tą etykietą będą przewidywane przez system autorytetu serwera. Dodatkowo, tylko właściwości i metody z tą etykietą mogą być dostępne wewnątrz funkcji powiązanych z RunService:BindToSimulation().

Tworzenie i usuwanie instancji

Wewnątrz funkcji powiązanych przez BindToSimulation() możesz tworzyć instancje za pomocą Instance.new(), Instance:Clone(), lub Instance.fromExisting(). Klient tworzy instancję natychmiast, a Roblox łączy ją z autorytatywną kopią serwera, gdy ta kopia dotrze. Aby uzyskać szczegóły, zobacz tworzenie instancji przewidywanych.

Usuwanie instancji działa inaczej. Instance:Destroy() nie ma dostępu do symulacji, a nie możesz zmienić Parent instancji, która jest już w DataModel, więc wywołanie któregokolwiek z nich wewnątrz powiązanej funkcji powoduje błąd. Zamiast tego, zarejestruj zamiar usunięcia instancji w atrybucie wewnątrz symulacji, a następnie usuń instancję na zewnątrz symulacji, na przykład w połączeniu PostSimulation na serwerze.

Skrypt serwera - Usuń instancję poza symulacją
local RunService = game:GetService("RunService")
local character = script.Parent
RunService.PostSimulation:Connect(function()
-- "SwordEquipped" jest zapisywane przez symulację, gdy gracz odrzuca miecz
local sword = character:FindFirstChild("Sword")
if sword and not character:GetAttribute("SwordEquipped") then
sword:Destroy()
end
end)

Akcje wejściowe

W grze opartej na autorytecie serwera głównym sposobem, w jaki klient może wpływać na stan gry, jest System Akcji Wejściowych. Te wejścia są wysyłane do serwera i są odtwarzane podczas ponownej symulacji na kliencie. W związku z tym InputActions powinny być używane do wszystkich wejść, które wpływają na podstawową symulację i powinny być sprawdzane pod kątem poprawności przed ich przetworzeniem.

Zauważ, że InputContexts musi być potomkiem Player, aby silnik wiedział, kto ma własność nad InputContext. Jednym z podejść jest dodanie swoich InputContexts do folderu w ReplicatedStorage i użycie Script w 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 wzoru, możesz odczytać InputActions dla wszystkich graczy w RunService:BindToSimulation() zarówno na kliencie, jak i serwerze, aby otrzymać te same dane dla danej klatki i zarejestrować wejście z poprzedniej klatki w atrybucie, na przykład, aby uruchomić bieg postaci, gdy wywołana zostanie akcja wejściowa RunAction.

Zdarzenia zdalne

Zdarzenia zdalne mogą być nadal używane w modelu autorytetu serwera do ułatwienia dyskretnej komunikacji między klientem a serwerem. Na przykład serwery mogą używać zdarzeń zdalnych do przesyłania danych o graczach zdobywających punkty lub podnoszących obiekty, a klienci mogą używać zdarzeń zdalnych jako alternatywnego interfejsu API do wysyłania wejść do serwera, takich jak naciśnięcia przycisków lub dotykanie obiektów w świecie 3D.

Animacje

Animacje, które wpływają na rozgrywkę, takie jak ruch postaci lub animacje ataku, powinny być kontrolowane wewnątrz funkcji powiązanych przez BindToSimulation() w tym samym ModuleScript, który działa zarówno na kliencie, jak i serwerze. Podstawowe człony Animator i AnimationTrack, takie jak LoadAnimation(), Play(), Stop(), AdjustSpeed(), i TimePosition mają dostęp do symulacji.

Stan animacji jest częścią przewidywanej symulacji. Gdy występuje cofnięcie podczas animacji, klient cofa animację do stanu autorytatywnego i odtwarza ją wraz z resztą symulacji, dzięki czemu animacje klienta i serwera pozostają zsynchronizowane. Ponieważ klient może zastąpić ścieżki animacji podczas cofania, nie przechowuj odniesień do AnimationTrack między klatkami. Zamiast tego, wyszukuj aktywną ścieżkę w każdej klatce za pomocą Animator:GetTrackByAnimationId(). Aby zobaczyć pełny przykład, zobacz pisanie kodu animacji.

Dźwięki i efekty

Efekty po stronie klienta, takie jak dźwięki i cząsteczki, muszą być pisane z myślą, że symulacja klienta jest jedynie przewidywaniem autorytatywnego stanu serwera. BindToSimulation() ogranicza, jakie właściwości i metody mogą być wywoływane z wewnątrz powiązanych funkcji, aby pomóc w pisaniu tylko do zsynchronizowanego stanu symulacji. Wyświetlanie wyników tej symulacji, wyzwalanie efektów i dźwięków itp. powinno odbywać się w osobnej funkcji połączonej z RenderStepped, która odczytuje wyniki symulacji i wyzwala pożądane efekty.

Ponieważ klient może przewidzieć zdarzenie, które nigdy nie występuje na serwerze, twój kod renderujący powinien być w stanie cofnąć lub ukryć błędne efekty przewidywania. Dalsze wskazówki dotyczące renderowania przewidywanej symulacji są omówione w odtwarzaniu dźwięków i efektów wizualnych.

Przykładowe projekty

Oprócz tej dokumentacji, następujące szablony mogą pomóc ci zacząć:

Wyścigi
Piłka nożna
Laser Tag
©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.