Wie dupliziere ich eine Box2d-Simulation während der Simulation?

7

Ich möchte den Status während des Spiels serialisieren, ihn über das Netzwerk an einen identischen Computer senden (dieselbe CPU, dasselbe Betriebssystem, dieselbe Binärdatei), ihn dort laden und die beiden Spiele zusammen ausführen lassen, wobei genau dieselbe Simulation ohne eines ausgeführt wird von ihnen abdriften und drunter und drüber gehen.

Kurz gesagt: Ich möchte Pop-In- und Pop-Out-Netzwerkunterstützung für mein hochphysikintensives Spiel, bei dem das Senden von Objektkoordinaten alle paar Sekunden unmöglich ist, da Tausende von Objekten und viele Clients vorhanden sind.

Ich habe dies mit Box2D versucht, und das Speichern der Position / Geschwindigkeit / usw. eines Objekts war nicht genug ... es gibt einen internen Status, auf den über keine öffentlichen Methoden zugegriffen werden kann.

Meine derzeitige Problemumgehung besteht darin, JEDEN Client zu zwingen, seinen gesamten Weltzustand zu speichern und ihn von Grund auf neu zu laden, wenn ein neuer Spieler eine Verbindung herstellt. Dies ist jedoch offensichtlich eine schlechte Vorgehensweise, da das Spiel für alle Spieler hängt, wenn eine neue Verbindung hergestellt wird. Es funktioniert jedoch ohne Desynchronisation.

Kennt jemand andere Techniken, die mir helfen können? Oder sollte ich mein Projekt einfach zum Abschied küssen?

Whyte
quelle
2
Interessante Frage, aber nach einem Motor zu fragen, ist wahrscheinlich kein Thema. Ich würde es umformulieren und einfach fragen: "Wie behebe ich das?". Wenn ein Motor in den Antworten landet, ist das kein Problem.
John McDonald
1
Sie müssten das Projekt nicht verschrotten, sondern nur die Popup-Unterstützung. Vielleicht könnten Sie unterwegs Kontrollpunkte haben? Orte, an denen das Spiel pausieren würde, damit neue Spieler beitreten können? Dies wäre zumindest eine erwartete Pause. Siehe auch: gamedev.stackexchange.com/questions/8619/… gamedev.stackexchange.com/questions/53887/… gamedev.stackexchange.com/questions/13789/…
MichaelHouse
Die Begrenzung der Zeiten, in denen Benutzer beitreten können, ist definitiv eine interessante Idee, an die ich nicht gedacht hatte ... und ich werde sie wahrscheinlich verwenden, um meine hässliche Problemumgehung ein wenig zu verbessern. Aber eine hässliche Problemumgehung ist immer noch eine hässliche Problemumgehung, egal wie Sie darauf blinzeln.
Whyte
Ich bin mit JBox2D zur gleichen Lösung gekommen. Ich baue die Welt auf jedem Client von Grund auf neu auf, wenn ein neuer Client beitritt, und es funktioniert auch für mich, wenn alles synchron bleibt. Bisher hatte ich mir Sorgen darüber gemacht, ob / wann es zu einem Problem wurde, aber ich bin froh, dass Sie diese Frage gestellt haben. Entschuldigung, ich bin nicht mehr Hilfe!
Venesectrix
1
Hier ist eine Idee: Was ist, wenn Sie die Welt im Hintergrund einige Aktualisierungen pro Aktualisierungsschleife von Grund auf neu erstellen? Wenn Sie dann zum Umschalten bereit sind, spielen Sie alle Befehle ab, die vom Beginn der Neuerstellung bis jetzt aufgetreten sind (um den neuen Aufbau bis zum aktuellen Status abzufangen), und schalten dann um. Es ist möglich, dass Sie einen kleinen Sprung von der Wiedergabe der Befehle in einen etwas anderen Physikzustand sehen, aber es sollte das Spiel nicht hängen lassen, während Sie zumindest die Welt neu aufbauen. Auch das könnte durch Interpolation verringert werden.
Venesectrix

Antworten:

1

Ich hatte das gleiche Problem (Synchronisieren von box2d-Welten für Browser-Clients mit world on node.js Server) und meine Lösung: Box2d-Welten im laufenden Betrieb synchronisieren - unmöglich. Also habe ich die gesamte Physik von Clients abgeschnitten, und jetzt empfangen sie diskrete zeitgestempelte Positionen von Objekten (und einigen Ereignissen) vom Server (auf dem box2d ausgeführt wird) und interpolieren zwischen ihnen. Box2d verwendet Werte, die in vorherigen Schritten generiert wurden, um den nächsten Schritt zu berechnen. Sie müssen also tief unter die Haube gehen, um box2d netzwerkkompatibel zu machen.

Zuker
quelle
Das ist der übliche Ansatz in Spielen und der, den ich zuerst in Betracht gezogen habe ... aber es ist nicht möglich, weil viele Gegenstände physisch aktiv sind und weil die Dinge in meinen Simulationen völlig anders laufen (ein Objekt würde einspringen eine völlig andere Richtung in weniger als 0,5 Sekunden nach der letzten Synchronisation).
Whyte
1
Vielleicht könnten Sie versuchen, eine Aktualisierungsrate von weniger als 0,5 Sekunden zu verwenden? In meinem Fall beträgt die Aktualisierungsrate 45 ms und es funktioniert ziemlich gut über den Websocket. Ein großer Teil des Netzwerkverkehrs könnte durch Komprimierung und Übertragung nur von Positionsdeltas reduziert werden. Außerdem können einige Teile der Physik auf dem Client implementiert werden, um sofort auf Benutzereingaben zu reagieren, oder es kann eine erweiterte Interpolation (nicht linear) verwendet werden.
Zuker
0

Führen Sie Ihre Simulation auf dem Server aus, senden Sie Clients zeitgestempelte Objektstatusaktualisierungen (deltakomprimiert) mit einer festen Rate, senden Sie andere Spielereignismeldungen, sobald sie auftreten, und lassen Sie Clients die Interpolation / Extrapolation zwischen Netzwerkstatusaktualisierungen durchführen. Sie müssen nicht Updates für alle Objekte im Spiel an alle Clients senden. Simulieren Sie den Kegelstumpf der Player-Kamera (3D) oder die Ansichtsrichtung (2D) auf dem Server und wählen Sie Ihren bevorzugten räumlichen Partitionierungsalgorithmus aus, um zu bestimmen, welche Objekte ein bestimmter Client sehen kann. Senden Sie nur Aktualisierungen für das, was ein Client sehen kann. Dadurch wird die CPU des Servers stärker belastet, das Netzwerkband auf dem Server wird jedoch auf einen vernünftigen Wert reduziert.

Homer
quelle