Aby zaoszczędzić przepustowość w mojej grze wieloosobowej , nie aktualizuję każdego obiektu co tik serwera, zamiast tego każdy obiekt ma updateRate, który informuje grę, że ten obiekt ma być aktualizowany co tik X serwera.
Kiedy otrzymuję komunikat o aktualizacji dla obiektu, obliczam czas, kiedy spodziewam się następnej aktualizacji:
origin = serverCurrentPosition
diff = serverNextPosition - origin
arriveTime = now + timeBetweenTicks * updateRate
Podczas rysowania obiektu obliczam czas pozostały do następnej aktualizacji i odpowiednio interpoluję pozycję:
step = 100 / timeBetweenTicks * updateRate
delta = 1 - step * ((arriveTime - now) / 100)
position = origin + diff * delta
Działa ... ale na rysunku wciąż jest trochę drgania, chociaż w mojej teorii wszystko powinno działać dobrze, ponieważ skalowanie powinno zająć pewną ilość opóźnienia, prawda?
Pytanie brzmi więc, czy to najlepsze podejście? Czy powinienem umieścić rzeczywiste opóźnienie w obliczeniach? Jeśli tak, jak mam to zrobić? Przeprowadziłem kilka eksperymentów, ale drgania tylko się pogorszyły.
źródło
Odpowiedzi:
Masz fluktuacje, ponieważ opóźnienie ciągle się zmienia. Oznacza to, że chociaż serwer wysyła aktualizacje dokładnie co
timeBetweenTicks
tyk, klient otrzymuje je po pewnym zmiennym czasie. Ten czas jest prawdopodobnie bliskitimeBetweenTicks
dobrego połączenia, ale nie do końca równy (a poza tym możesz mieć opóźnienie serwera i różne prędkości zegara na serwerze i kliencie).Tak więc, kiedy polegasz na otrzymaniu aktualizacji w dokładnie określonym czasie, stale docierasz do miejsca docelowego nieco przed / po faktycznej aktualizacji. Stąd jitter.
Prostym podejściem do zmniejszenia jittera jest użycie „gumowania”, co sugeruje Martin w innej odpowiedzi. Zasadniczo po otrzymaniu aktualizacji nie zmienia się natychmiast pozycji obiektu. Zamiast tego, jeśli pozycja klienta i pozycja serwera różnią się tylko nieznacznie, zaczniesz interpolować pozycję klienta, aby po pewnym czasie (powiedzmy, w połowie drogi do następnej aktualizacji) pozycje klienta i serwera zbiegły się.
Kolejny pomysł na zmniejszenie drgań w konfiguracji: ponieważ przesyłasz zarówno współrzędne „bieżące”, jak i „następne”, możesz obliczyć prędkość obiektu. Następnie, gdy aktualizacja się opóźnia, nie zatrzymujesz obiektu w jego miejscu docelowym (tj. W pozycji „następnej”), ale kontynuujesz przesuwanie go z tą samą prędkością. Jeśli twoje obiekty nie zmieniają gwałtownie prędkości, to naprawdę poprawi płynność ruchu na kliencie.
źródło
Problem ten rozwiązałem już wcześniej z pewnym powodzeniem, stosując podejście, które nazywam „cieniami sieci”. Nie wiem, czy robią to inni ludzie, ale zawsze działało to dla mnie.
Każdy byt, który jest synchronizowany w sieci, ma niewidoczny byt sieciowy. Gdy aktualizacja nadchodzi z sieci, teleportujesz cień bezpośrednio do pozycji, w której sieć mówi, że powinna być, a następnie powoli interpolujesz lokalny widoczny obiekt w kierunku cienia w czasie.
W mojej poprzedniej odpowiedzi tutaj zamieściłem wiele szczegółów na temat tego podejścia
źródło
Napisałem artykuł opisujący nieco inne podejście, które daje bardzo płynne wyniki: http://www.gabrielgambetta.com/fpm3.html
źródło