Co wysłać na serwer w czasie rzeczywistym w grze FPS?

23

Jaki jest właściwy sposób, aby poinformować serwer o pozycji naszego lokalnego gracza? Niektóre dokumenty mówią, że lepiej jest wysyłać dane wejściowe za każdym razem, gdy są produkowane. Niektóre dokumenty mówią, że klient przesyła swoją pozycję w ustalonych odstępach czasu.

Z podejściem wysyłania danych wejściowych: Co powinienem zrobić, jeśli gracz przytrzymuje klawisze kierunkowe? Oznacza to, że muszę wysłać paczkę do serwera w każdej ramce. Czy to nie za dużo? Istnieje również obrót odtwarzacza z wejścia myszy. Oto przykład:

http://www.gabrielgambetta.com/fpm_live.html

Co z wysyłaniem pozycji w podejściu z ustalonym interwałem. Wysyła za mało wiadomości do serwera. Ale zmniejsza również czas reakcji.

Więc która droga jest lepsza?

syloc
źródło

Odpowiedzi:

19

Prosta odpowiedź: oszukiwać lub nie być tak dokładne!

Jeśli grałeś w jakąś strzelankę online, najprawdopodobniej doświadczyłeś tak zwanej „gumki”, jeśli twoje połączenie z serwerem jest złe.

Jest to spowodowane tym, że klient od czasu do czasu koryguje Twoją pozycję.

Zasadniczo co dzieje się po obu stronach:

  • Serwer będzie śledził Twój ruch i wysyłał aktualizacje do klientów zgodnie z oczekiwaniami. Nie zawsze muszą to być pełne aktualizacje. Każda x ramek może zawierać pełną aktualizację, wszystkie pozostałe ramki wysyłają tylko nowe wektory prędkości (jeśli są jakieś zmiany).

  • Twój własny klient pozwoli ci swobodnie się poruszać, ale będzie korzystał z aktualizacji dostarczonych przez serwer, aby poprawić / skorygować swoją pozycję. Dzięki temu gra będzie czuć się responsywna, nawet jeśli nie aktualizujesz pozycji klatka po klatce.

Ale w jaki sposób obsługiwane są dane wejściowe? Twój klient wyśle ​​Twoją pozycję na serwer „Przeprowadziłem się tam”. Serwer zweryfikuje tę aktualizację (np. Czy możesz tam się tak szybko przenieść?) I jeśli jest ona prawidłowa, przenieś cię (lub odrzucisz aktualizację, co spowoduje „gumowanie”).

Więc tak, twoje podejście z ustalonym interwałem najprawdopodobniej zadziała i wystarczy.

Ale nawet jeśli chcesz wysłać dane wejściowe i obsłużyć ruch po obu stronach, pamiętaj, że nie musisz wysyłać „przycisk jest nadal wciśnięty”. Zamiast tego wyślij jedno zdarzenie po naciśnięciu przycisku, a drugie po zwolnieniu przycisku.

Mario
źródło
5
Tak, mogę śledzić naciśnięcie i zwolnienie przycisku. Ale co z wejściem myszy? To się ciągle zmienia.
syloc
6
„Zamiast tego wyślij jedno zdarzenie po naciśnięciu przycisku, a drugie po zwolnieniu przycisku.” - To prawda, ale konieczne są kontrole, aby upewnić się, że zdarzenie „w momencie wydania” zostanie ostatecznie wymuszone, w zależności od zasad gry. Na przykład w grze wieloosobowej Rainbow Six Vegas 2 gracz może rozpocząć strzelanie, a (niestety częsty) błąd powoduje, że komunikat „przestań strzelać” nie dociera do serwera. Powoduje to, że dźwięk postrzału pozostaje w nieskończonej pętli do końca meczu. Tylko jeden przykład, na który należy uważać. youtu.be/GOQIbLCy7m8?t=9m10s
Mike Baxter
@syloc: Wystarczy poradzić sobie z tym po stronie klienta i pozwolić serwerowi ustalić, czy ruch jest prawidłowy / możliwy (aby zapobiec takim rzeczom, jak włamania do teleportacji itp.).
Mario
@syloc Wystarczy ustawić interwał dla myszy, ale aby zaoszczędzić dodatkową przepustowość, nadal sprawdzaj po stronie klienta, czy jest zmieniona. Jeśli jest czas bez ruchu myszy, nie musisz ciągle wysyłać wiadomości na ten temat.
agweber
W jednym z moich zadań inżynier praktycznie doprowadził się do szaleństwa, optymalizując zachowanie sprężyny pod kątem nieudanych aktualizacji pozycji podczas połączenia telefonicznego (13 lat temu). Teraz widzę gry z dużą przepustowością i absurdalnie niskim opóźnieniem cierpiące z powodu tego problemu, wydaje się, że problem ten nigdy nie zniknie lub że ludzie mniej się tym teraz przejmują.
Andon M. Coleman
5

Jeśli jeszcze tego nie zrobiłeś, proponuję przeczytać dwa głębokie, ale zrozumiałe artykuły: https://developer.valvesoftware.com/wiki/Source_Multiplayer_Networking i http://fabiensanglard.net/quake3/network.php .

Wyjaśniają one, dlaczego zaleca się wysyłanie pakietów w ustalonych odstępach czasu. Krótko mówiąc, jest to szczególnie ważne w przypadku pakietów wysyłanych przez serwer.

Wysłanie pakietu ma stały koszt, a maksymalny rozmiar pakietu sieciowego wynosi około 1,5 KB. Jeśli więc masz na przykład 16 graczy na serwerze, każda klatka podczas obliczania ruchu dla gracza, naiwny kod może wysłać pakiet aktualizacji do każdego gracza po każdej rozdzielczości ruchu, więc 16 * 16 = 256 pakietów. Jeśli masz 30 klatek na sekundę, to 7680 pakietów.

Lepszym podejściem jest utworzenie bufora na każdym początku ramki, połączenie w nim aktualizacji 16 obliczonych pozycji, a następnie wysłanie ich do 16 graczy.

Teraz wysyłasz tylko 480 pakietów na sekundę dla tych samych wyników.

W przypadku odtwarzacza z serwerem oznacza to po prostu, że w tym samym pakiecie należy przesłać maksymalnie dane, takie jak; wyglądała pozycja, działania nazywane tą ramką i tak dalej.

O drugiej części twojego pytania - sposobem, w jaki zdecydowałem się zmniejszyć odczucie opóźnienia, było wysłanie tych informacji do serwera w każdej ramce:

  • aktualna bieżąca pozycja gracza (używana przez serwer do sprawdzenia, czy pozycje po stronie serwera i po stronie gracza nie są zbytnio zsynchronizowane).

  • Szacowana pozycja gracza w ciągu 1 sekundy: obliczona przez klienta: jeśli gracz nie zmieni kierunku myszy i pozostawi klawiaturę w obecnym stanie na 1 sekundę, gdzie będzie gracz? (nie dbamy o kolizje) Jeśli gracz się nie porusza, jego szacunkowa pozycja w ciągu 1 sekundy jest jego aktualną pozycją.

  • Pozycja, na którą patrzy.

Za każdym razem, gdy serwer otrzymuje te informacje, aktualizuje przyszłą pozycję i wyglądaną pozycję, a podmiot gracza ostatecznie przesuwa się w kierunku swojej przyszłej pozycji.

Gracze nigdy nie są dokładnie zsynchronizowani, ale odpowiedź wejściowa jest natychmiastowa (najważniejsze dla mnie) i stwierdziłem, że przewidywane pozycje są dla mnie wystarczająco dokładne.

GaelFG
źródło
„Gracze nigdy nie są dokładnie zsynchronizowani” Myślę, że ważne jest również, aby wspomnieć, że poziom dokładności zależy tutaj od rzeczywistej gry (gry). Na przykład klasyczna gra MMO, w której wystarczy kliknąć i wybrać byty, nie będzie wymagała doskonałej dokładności dla prawie wszystkiego, ale w strzelance dobra synchronizacja jest niezbędna.
Mario,
Rzecz w tym, że nikt przy zdrowych zmysłach nie używa TCP do FPS. Woleliby raczej poradzić sobie ze skomplikowaną ponowną sekwencją i pominiętymi datagramami niż ponieść narzut TCP.
Andon M. Coleman,