Um in meinem Multiplayer-Spiel Bandbreite zu sparen , aktualisiere ich nicht jedes Objekt bei jedem Server-Tick, sondern jedes Objekt hat eine updateRate, die dem Spiel mitteilt, dass dieses Objekt voraussichtlich bei jedem X-Server-Tick aktualisiert wird.
Wenn ich eine Aktualisierungsnachricht für ein Objekt erhalte, berechne ich den Zeitpunkt, zu dem die nächste Aktualisierung eintrifft:
origin = serverCurrentPosition
diff = serverNextPosition - origin
arriveTime = now + timeBetweenTicks * updateRate
Wenn ich das Objekt zeichne, berechne ich die verbleibende Zeit bis zur nächsten Aktualisierung und interpoliere die Position entsprechend:
step = 100 / timeBetweenTicks * updateRate
delta = 1 - step * ((arriveTime - now) / 100)
position = origin + diff * delta
Es funktioniert ... aber es gibt immer noch ein bisschen Jitter in der Zeichnung, obwohl in meiner Theorie alles gut funktionieren sollte, da die Skalierung eine gewisse Verzögerung ausgleichen sollte, oder?
Die Frage hier ist also, ist dies der beste Ansatz? Soll ich die tatsächliche Verzögerung in die Berechnung einbeziehen? Wenn ja, wie würde ich das machen? Ich habe einige Experimente durchgeführt, aber der Jitter wurde nur schlimmer.
quelle
Antworten:
Sie haben Jitter, weil Sie sich ständig ändern. Das heißt, während der Server genau alle
timeBetweenTicks
Ticks aktualisiert , erhält der Client diese nach einer variablen Zeit. Diese Zeit ist wahrscheinlich in der NähetimeBetweenTicks
einer guten Verbindung, aber nicht genau gleich (und außerdem kann es zu Server-Verzögerungen und unterschiedlichen Taktraten auf Server und Client kommen).Wenn Sie also darauf vertrauen, dass Sie das Update genau zur angegebenen Zeit erhalten, kommen Sie immer etwas vor / nach dem eigentlichen Update am Ziel an. Daher Jitter.
Ein einfacher Ansatz zur Reduzierung von Jitter ist die Verwendung von "Gummibändern", was Martin in einer anderen Antwort vorschlägt. Grundsätzlich ändert sich die Position des Objekts nicht sofort, wenn Sie eine Aktualisierung erhalten. Wenn sich die Clientposition und die Serverposition nur geringfügig unterscheiden, interpolieren Sie die Clientposition, sodass Client- und Serverposition nach einer bestimmten Zeit (etwa auf halbem Weg zur nächsten Aktualisierung) zusammenlaufen.
Eine weitere Idee zur Reduzierung von Jitter in Ihrem Setup: Da Sie sowohl "aktuelle" als auch "nächste" Koordinaten übertragen, können Sie die Geschwindigkeit des Objekts berechnen. Wenn die Aktualisierung verzögert ist, stoppen Sie das Objekt nicht an seinem Ziel (dh an der "nächsten" Position), sondern bewegen es mit derselben Geschwindigkeit weiter. Wenn Ihre Objekte ihre Geschwindigkeit nicht abrupt ändern, verbessert dies die Bewegungsruhe auf dem Client.
quelle
Ich habe dieses Problem bereits mit einigem Erfolg mit einem Ansatz gelöst, den ich "Netzwerkschatten" nenne. Ich weiß nicht, ob das etwas ist, was andere Leute tun, aber es hat immer für mich funktioniert.
Jede Entität, die über das Netzwerk synchronisiert wird, verfügt über eine unsichtbare Netzwerkschattenentität. Wenn ein Update vom Netzwerk eingeht, teleportieren Sie den Schatten direkt an die Position, an der sich das Netzwerk befinden soll, und interpolieren dann langsam die lokal sichtbare Entität in Richtung des Schattens.
Ich habe in meiner vorherigen Antwort hier viele Details zu diesem Ansatz aufgenommen
quelle
Ich habe einen Artikel geschrieben, der einen etwas anderen Ansatz beschreibt, der zu sehr glatten Ergebnissen führt: http://www.gabrielgambetta.com/fpm3.html
quelle