Wdrażam klon asteroid dla wielu graczy, aby dowiedzieć się o architekturze sieci klient / serwer w grach. Spędziłem czas czytając publikacje GafferOnGames i Valve na temat ich technologii klient / serwer. Mam problem z dwoma koncepcjami.
Obecnie mam autorytatywny serwer gier symulujący fizykę z box2d i wysyłający klientom informacje o stanie świata około 20 razy na sekundę. Każdy klient śledzi kilka ostatnich migawek, które otrzymał, i przeskakuje między dwoma stanami, aby wygładzić ruch duszków. Jednak nie jest tak gładkie. Przez jakiś czas może być gładka, potem trochę szarpana, potem z powrotem gładka itp. Próbowałem zarówno TCP, jak i UDP, oba są mniej więcej takie same. Masz pojęcie, jaki może być mój problem? (Uwaga: zaimplementowałem to najpierw dla jednego gracza, a ruch duszka jest idealnie płynny przy 60 fps przy aktualizacji świata fizyki tylko 20 razy na sekundę).
Aby rozwiązać pierwszy problem, pomyślałem, że może klient powinien również uruchomić symulację box2d i po prostu zaktualizować pozycje swoich ikonek, aby pasowały do migawek serwera, gdy się nie zgadzają. Pomyślałem, że może to być płynniejsze, ponieważ moja implementacja dla jednego gracza jest płynna. Czy to dobry pomysł?
Nawet jeśli nie rozwiąże powyższego problemu, czy jest to konieczne do przewidywania po stronie klienta? Na przykład, jeśli gracz spróbuje poruszyć swój statek, skąd będzie wiedział, czy trafił w asteroidę, ścianę lub statek wroga bez symulacji fizyki? Wygląda na to, że ich statek wydaje się przechodzić przez obiekt, z którym powinien się zderzyć, zanim otrzymają migawkę z serwera, która mówi, że uderzyła w obiekt.
Dzięki!
źródło
+-*/
” jest całkowicie fałszywe. Wszystkie te operacje w IEEE-754 mogą się różnić w zależności od implementacji. Zobacz tutaj i tutaj, aby uzyskać więcej informacji.Prawdopodobnie nie wygląda to tak dobrze, ponieważ interpolacja między nimi polega na tym, że zawsze mamy następny zestaw danych do interpolacji. Oznacza to, że jeśli występuje krótki skok opóźnienia, wszystko musi poczekać, aby nadrobić zaległości.
W GameDev znajduje się stary artykuł na temat używania splajnów sześciennych do przewidywania położenia obiektu poza punktem, w którym ostatnio miałeś dla niego dane. Następnie wykorzystaj tę pozycję, a następnie dostosuj splajn, gdy uzyskasz nowe dane uwzględniające jego nową pozycję. Jest to również prawdopodobnie znacznie tańsze niż przeprowadzanie drugiej symulacji fizyki, a to oznacza, że nie musisz decydować o tym, komu ufasz, ponieważ jawnie zaimplementowałeś klienta tworzącego go na bieżąco. :)
źródło
Sam zrobiłem podobne rzeczy i uruchomiłem Box2D tylko na klientach. Sposób, w jaki to zrobiłem, polegał na tym, aby pozwolić klientowi na uruchomienie własnej symulacji, wysyłając bieżącą prędkość (i rotację) każdego pakietu synchronizacji do serwera. Serwer następnie wysyła te informacje do innych graczy, którzy ustawiają nowo otrzymane prędkości replikowanym bytom. Był bardzo płynny, bez zauważalnych różnic między klientami.
Oczywiście problem polega na tym, że nie ma scentralizowanej kontroli nad bytami, ale myślę, że można to zrobić również po stronie serwera, wykonując symulację fizyki po stronie serwera
źródło
Osobiście wolałbym uruchamiać symulacje tylko na serwerze i przekazywać mu wszelkie zmiany prędkości / przyspieszeń liniowych / kątowych zaangażowanych obiektów, ilekroć się one zdarzają. To jest, gdy jakiś obiekt, z jakiegokolwiek powodu, zmienia dowolne jego właściwości fizyczne (takie jak wspomniane prędkości i przyspieszenia), ta konkretna zmiana zostanie wysłana z serwera do klienta, a klient zmieni stronę odpowiednio dane obiektu.
Przewaga nad obecną implementacją polega na tym, że unieważnia konieczność interpolacji po stronie klienta i generuje bardzo wierne zachowanie na obiektach. Problem polega na tym, że ta metoda jest bardzo podatna na opóźnienia, które stają się bardzo dużym problemem, gdy gracze są zbyt daleko od siebie geograficznie.
Jeśli chodzi o pytanie 1, mówię, że problemem byłyby fluktuacje opóźnienia, ponieważ nie ma absolutnej gwarancji, że będzie dokładnie idealny 20 sekundowy odstęp między każdym odbieraniem migawki. Pozwól mi zilustrować (będący „t” czasem mierzonym w milisekundach):
1) Przy t = 20 od początku gry klient otrzymał migawkę i wykonał interpolację z powodzeniem i płynnie.
2) Przy t = 40 wystąpiło opóźnienie między serwerem a klientem, a migawka faktycznie osiągnęła tylko t = 41.
3) Przy t = 60 serwer wysłał kolejną migawkę, ale jedna sekunda symulacji została zmarnowana po stronie klienta z powodu opóźnienia. Jeśli migawka dotrze do t = 60, klient nie wykona interpolacji 40 i 60 instancji, ale faktycznie od instancji 41 do 60, generując inne zachowanie. Ta niedokładność może być przyczyną ostatecznego „szarpnięcia”.
Jeśli chodzi o pytanie 2, Twój pomysł może zadziałać, jeśli zaimplementujesz coś, co skutecznie sprawdzi, czy każdy obiekt jest rzeczywiście zsynchronizowany klient-serwer, bez konieczności wysyłania pakietów z każdą ramką informujących o położeniu obiektów. Nawet jeśli robisz to w dyskretnych odstępach czasu, nie tylko napotkasz ten sam problem z pytania 1, ale także będziesz mieć zbyt duże ilości danych, aby je przesyłać (co jest złą rzeczą).
źródło