Czy przeprowadzić symulację fizyki na kliencie i serwerze?

13

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.

  1. 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ę).

  2. 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!

Venesectrix
źródło

Odpowiedzi:

10

Zdecydowanie uruchom symulację zarówno na kliencie, jak i na serwerze. Wszystko inne ma zbyt długie opóźnienia. Należy upewnić się, że symulacje są zgodne, wstawiając obiekty w tej samej kolejności, stosując stały krok czasowy i unikając porównywania wskaźników. Nie próbowałem tego z Box2D, ale generalnie możliwe jest osiągnięcie takiego samego zachowania na wszystkich maszynach w symulacji fizyki. Cała matematyka jest zwykle oparta na liczbach zmiennoprzecinkowych IEEE 754 binary32, a ich zachowanie jest ściśle określone dla operacji takich jak np +-*/. Kilka. Musisz być ostrożny sin,cosi lubi trudne, ponieważ mogą się różnić między środowiskami wykonawczymi (jest to szczególnie ważne przy programowaniu dla wielu platform). Upewnij się także, że w kompilatorze używasz ścisłych ustawień optymalizacji pływających. Nadal możesz synchronizować obiekty, okresowo wysyłając stan obiektów z serwera. Nie aktualizuj, chyba że różnica jest większa niż próg, aby uniknąć niepotrzebnego jąkania.

Jednym z nasuwających się problemów jest tworzenie nowych obiektów i to, jak zmieni to symulację między klientami. Jednym ze sposobów rozwiązania tego problemu jest zezwolenie serwerowi na tworzenie wszystkich obiektów. Jeśli bieżącym krokiem jest t, serwer zaplanuje dodanie obiektu o t+d. Tak więc lista nowych obiektów z obiektami do dodania i terminem ich dodania może być utrzymywana na wszystkich klientach i aktualizowana przez serwer z dużym wyprzedzeniem. Jeśli djest wystarczająco duży, minimalizujesz ryzyko różnych wyników. Jeśli naprawdę nie potrafisz poradzić sobie z różnicą, możesz zmusić klienta do oczekiwania na informacje o nowych obiektach przez określony czas przed symulacją tego kroku czasu.

rasmus
źródło
Dzięki za twoją odpowiedź. Nie sądzę, że box2d gwarantuje takie same wyniki na różnych procesorach, co byłoby dla nas scenariuszem, odkąd piszemy grę komputerową. Mam nadzieję, że różnice będą niewielkie i łatwe do skorygowania dzięki okresowym aktualizacjom z wiarygodnego serwera, ale nigdy tego nie próbowałem.
Venesectrix
Erin Catto uważa, że ​​próba utrzymania całego stanu wielu światów Box2D w synchronizacji to przegrana bitwa ( box2d.org/forum/viewtopic.php?f=3&t=8462 )
Pavel
Stwierdzenie „IEEE 754 binary32 floats [..] zachowanie jest ściśle zdefiniowane dla operacji takich jak +-*/ 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.
BlueRaja - Danny Pflughoeft
1
Nie. To całkowicie prawda. Problem opisany przez twój link jest związany z różnymi trybami procesora x87 i implementacjami transcendentałów. IEEE 754 binary32 jest ściśle zdefiniowany dla podstawowych operacji. To od Ciebie zależy, czy ustawisz właściwe tryby i zastosujesz odpowiednie instrukcje, aby przestrzegać normy. Używanie instrukcji SSE, a nie procesora x87, bardzo pomaga.
rasmus
4

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. :)

Matt Kemp
źródło
Może tak być. Staram się opóźnić, dopóki nie otrzymam 3 migawek z serwera. W punkcie I lerp od strzału 1 do strzału 2. Następnie od strzału 2 do strzału 3. Jeśli w dowolnym momencie przegapię pakiet, mogę lerp od 1 do 3, zamiast 1 do 2, jeśli ma to sens. Być może jednak nie wdrażam tego poprawnie. Dzięki za link do artykułu!
Venesectrix
1

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

manabreak
źródło
Dzięki za wkład. Będziemy potrzebować scentralizowanej kontroli, aby zapobiec oszustwom, dlatego musimy mieć przynajmniej symulację serwera, aby wiedzieć, czy to, co mówią klienci, jest możliwe, czy nie.
Venesectrix
1

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ą).

UBSophung
źródło
Nie jestem pewien, czy podążam za tym, co mówisz w pierwszym akapicie. Jeśli symulacja działa tylko na serwerze, a ty transmitujesz tylko zmiany prędkości / przyspieszenia, to skąd klient wie, gdzie powinny być rysowane duszki? Klienci musieliby symulować obiekty na podstawie otrzymanej prędkości / przyspieszenia, aby poprawnie je narysować. Myślę, że masz rację co do otrzymywania migawek w odstępach innych niż dokładnie to, czego oczekuję. Masz pomysł, jak sobie z tym poradzić?
Venesectrix
Klienci wiedzą początkowych i aktualnych pozycji, prędkości i przyspieszeń obiektów i zaktualizuje stanowisko to uważa obiekty są (niezależnie od serwera) odpowiednio. Serwer ostatecznie zmieni takie właściwości na klientach za pomocą komunikatów, ponieważ to on dokonuje fizyki i
wykrywa