Zobaczmy na techniki jakimi programiści radzą sobie z opóźnieniami w grach multiplayer.
Netcode
Zasadniczo kod sieciowy (netcode) jest po prostu metodą komunikacji między dwoma lub więcej komputerami, z których każdy ma uruchomioną tę samą grę. Podczas gdy gra lokalna zawsze zapewnia, że wszystkie dane wejściowe gracza docierają i są przetwarzane w tym samym czasie, sieci są stale niestabilne w sposób, którego gra nie może kontrolować ani przewidywać. Informacje wysyłane do przeciwnika mogą być opóźnione, niepoprawne lub całkowicie utracone w zależności od kilkudziesięciu czynników, w tym fizycznej odległości do przeciwnika, połączenia Wi-Fi oraz tego, czy współlokator ogląda Netfliksa.
Wśród gier online bijatyki mają swój własny zestaw unikalnych wyzwań. Tutaj niskie, stałe opóźnienie jest niezwykle ważne, ponieważ pamięć mięśniowa i reakcje są podstawą praktycznie każdej gry tego typu. W rezultacie pojawiły się dwie podstawowe strategie programowania netcode w takich grach online: kod sieciowy oparty na opóźnieniu (delay-based netcode) i kod sieciowy oparty na wycofywaniu (rollback netcode). Obecnie częściej stosowaną techniką w bijatykach jest rollback netcode.
Na czym polega problem?
W grach walki czas jest mierzony w jednostce zwanej klatką. Aby ułatwić dyskusję, przyjmiemy, że wszystkie bijatyki działają w 60 klatkach na sekundę, co oznacza, że jedna klatka to około 16 milisekund (ms) czasu rzeczywistego. Przesłanie informacji przez sieć zawsze wymaga czasu. Jest to mierzone w pingu, czyli czasie potrzebnym na przesłanie informacji do drugiego gracza, a następnie z powrotem do Ciebie. Na przykład w przypadku połączenia z pingiem 90 ms potrzeba (średnio) 45 ms, aby informacja dotarła na drugą stronę, czyli około 3 klatek w grze. Oznacza to, że gry muszą sobie jakoś sprytnie radzić z obsługą opóźnień żeby zachować płynność rozgrywki i zasady fair play.
Kiedy gry przesyłają informacje do siebie, a następnie polegają na komputerach, aby niezależnie przeprowadzać zsynchronizowane symulacje, mówi się, że używają sieci lockstep. Nie rozmawiają więc z centralnym serwerem, który śledzi za nich grę i mówi im, co mają robić. Zamiast tego pilnują siebie, pytając się nawzajem okresowo, czy mają ten sam stan gry. Jeśli gry zaczną się nie zgadzać co do stanu gry, zostaną zdesynchronizowane i prawdopodobnie będą musiały po prostu całkowicie zarzucić rozgrywkę. Gry rozmawiające ze sobą bezpośrednio mogą być często szybsze niż zmuszanie ich do rozmowy przez pośrednika, a rozwiązania typu lockstep są szczególnie dobre w zapobieganiu wielu rodzajom oszustw.
Jeśli więc mamy taką grę walki, która korzysta z sieci lockstep, jedyne, czego potrzebujemy do rozgrywania meczów online, to dane wejściowe od obu graczy. Ale jak to zrobić, żeby wszystko działało?
Delay-based netcode
Pierwsza strategia jest najprostszą i najpowszechniejszą implementacją w grach korzystających z lockstep. Jeśli ruchy zdalnego gracza docierają z opóźnieniem, ponieważ muszą zostać wysłane przez sieć, strategie oparte na opóźnieniach po prostu sztucznie opóźniają ruchy lokalnego gracza o ten sam czas. Wtedy, teoretycznie, oba ruchy „pojawią się” w tym samym czasie i mogą zostać wykonane w tej samej klatce, tak jak tego oczekiwano.
Sprawdź oferty pracy na TeamQuest
To rozwiązanie ma istotną wadę. Ponieważ sieci są notorycznie niestabilne, strategie oparte na opóźnieniach borykają się z trudnościami, ponieważ są kiepskie w radzeniu sobie z fluktuacjami sieci. Załóżmy, że połączenie jest szarpane, a dotarcie do niektórych informacji od przeciwnika zajmuje trochę więcej czasu niż np. 3 klatki. Ponieważ gra po prostu nie może być kontynuowana bez informacji od obu graczy, nie ma innego wyjścia, jak zatrzymać się i poczekać na nadejście danych wejściowych, co powoduje, że gra zatrzymuje się w chwilach przedłużających się problemów z siecią.
rollback netcode
W tej technice w przypadku braku danych zdalnych kod sieciowy będzie nadal symulował grę. Ale kiedy te dane wejściowe w końcu pojawią się, gra posunie się do przodu w czasie, gdy przeciwnik nacisnął ten przycisk, a gra już przecież wyświetli inny wynik na ekranie. To nie tak powinno być. Więc aby to naprawić, rollback netcode przewinie symulację, zastosuje prawidłowe dane wejściowe i natychmiast pokaże nowy wynik graczowi. Czyli to, co pokazaliśmy graczowi w ostatnich 3 klatkach, nie będzie tym, co naprawdę się wydarzyło, a gra musi naprawić przeszłość, wykonując pewne obliczenia w tle.