Ich arbeite an einem Entitätssystem für ein vernetztes Spiel und ordne jeder Entität eine eindeutige 32-Bit-Ganzzahl-ID zu, mit der ich Verweise auf Entitäten und die Entitäten selbst serialisieren kann.
Derzeit erhöhe ich nur einen Zähler jedes Mal, wenn eine Entität erstellt wird. Ich schätze, die IDs werden irgendwann aufgebraucht sein, aber ich erwarte nicht wirklich 4 Milliarden Entitäten. Auch dies vermeidet das Problem, wenn die Entität Nr. 5 zerstört wird und wir eine ID von 5 erhalten. Soll dies auf die neue Nr. 5 oder die alte gelöschte Nr. 5 verweisen?
Das Problem ist, dass ich nicht sicher bin, wie ich mit Kollisionen umgehen soll. Wenn ein Client derzeit ein Update für eine Entität mit einer höheren ID als der aktuellen "freien ID" erhält, wird die freie ID bis dahin nur angetastet. Das scheint aber nicht sehr robust zu sein.
Ich habe darüber nachgedacht, jedem Client möglicherweise Bereiche zuzuweisen, damit er Entitäten ohne Konflikte zuordnen kann (die obersten n Bits sind die Spielernummer), aber ich mache mir Sorgen darüber, was passiert, wenn sich Bereiche im Laufe der Zeit überlappen.
Gibt es eine bessere Möglichkeit, damit umzugehen? Sollte ich mich überhaupt darum kümmern, dass IDs überlaufen oder das Ende des zulässigen Bereichs überschritten wird? Ich könnte Code hinzufügen, um diese Fälle zu erkennen, aber was würde es tun, wenn sie nicht zum Absturz führen.
Eine andere Möglichkeit ist die Verwendung einer 128-Bit-GUID, bei der die Wahrscheinlichkeit höher ist, dass sie eindeutig ist. Bei einem Spiel, das versucht, den Netzwerkverkehr zu minimieren, scheint dies jedoch sehr schwer zu sein. Realistisch gesehen würde ich nie mehr Entitäten auf einmal benötigen, als in eine 32-Bit- oder sogar 24-Bit-Ganzzahl passen würden.
Vielen Dank!
quelle
Antworten:
Was ich getan habe, ist, den Server alles machen zu lassen . Die Clients können den Server lediglich auffordern, etwas zu tun, aber selbst nichts tun. In diesem Fall ist der Server immer derjenige, der IDs zuweist, und das Problem ist behoben.
Ich habe mich nicht mit clientseitigen Vorhersagen befasst, während ich darauf gewartet habe, dass der Server Aktionen wie "Eine Rakete abschießen" oder "Hier eine Solarstation erstellen" genehmigt. Diese Aktionen möchten Entitäten erstellen, und Entitäten haben IDs. Bisher sitze ich nur auf meinem Daumen und warte auf den Server, aber ich glaube, Sie müssen eine temporäre Entität erstellen, während Sie auf die Servergenehmigung warten. Wenn Sie die Servergenehmigung erhalten, weist der Server eine ID zu und Sie können das temporäre Objekt entweder aktualisieren oder überschreiben.
Ich habe mich auch nicht mit einem ID-Überlauf befasst, aber wenn der Server die volle Kontrolle hat und einen Überlauf feststellt, kann er alles tun, was Sie für erforderlich halten (Neustart bei 0, Auswahl von einem freien Stapel, Absturz usw.) Die Kunden werden es nicht einmal wissen oder sich darum kümmern. Die Clients akzeptieren nur die vom Server ausgegebenen IDs.
quelle
Als ich dies für ein kommerzielles Multiplayer-Spiel getan habe, habe ich genau das getan, was Sie vorgeschlagen haben: Verwenden Sie eine 32-Bit-GUID-Ganzzahl, wobei die oberen acht Bits die Spielernummer sind und die unteren vierundzwanzig Bits eine lokal eindeutige Nummer enthalten.
Wenn / wenn die lokale Nummer überläuft (in meinem Fall würde dies so gut wie nie passieren; bei normaler Verwendung hätte es vier bis fünf Tage ununterbrochener Spielzeit in einer einzelnen Netzwerksitzung gedauert, bis dies passierte), würde der Eigentümer eine E-Mail senden Die Meldung "Alle meine Objekte zurücksetzen" und alle noch vorhandenen Objekte neu nummerieren, beginnend mit Null vor. Die Nachricht forderte alle Peers auf, empfangene Objekte zu verwerfen und erneut nach ihnen zu fragen.
Ein ausgefallenerer Ansatz wäre die Meldung "Objekt mit GUID 'n' ist jetzt Objekt mit GUID 'm'" für jedes vorhandene Objekt. In meinem Fall war es jedoch unwahrscheinlich, dass dies jemals tatsächlich eintrat, und ich hätte nicht gedacht, dass es den Menschen wirklich etwas ausmachen würde, wenn entfernte Objekte nach fünf Tagen ununterbrochener Wiedergabe in einer einzigen Netzwerksitzung für eine halbe Sekunde aus der Welt verschwinden würden. ;)
quelle
Wenn Ihre Kunden ihre eigenen Einheiten erzeugen können, haben Sie vermutlich ein Peer-to-Peer-Multiplayer-Spiel.
In diesem Fall haben Sie wahrscheinlich nicht zu viele Kunden. Sicherlich nicht mehr als 256. Und Ihre Entity-ID passt garantiert in 24 Bit (16000000+ Entities sind genug für alle!). Machen Sie einfach das höchste Byte Ihrer ID gleich der ID des Clients:
oder so.
Und wenn ich mich irre und Sie einen autorisierenden Server haben, erstellen Sie niemals neue Entitäten auf Clients.
quelle
Ich verwende die 'naivste' Methode (erhöhe einfach eine Ganzzahl für jede neue ID) in meinem beständigen Multiplayer-Spiel und sie funktioniert einwandfrei, da ich nicht zulasse, dass der Client neue IDs erstellt.
Wenn Sie den Kunden entscheiden lassen (indem Sie eine Art GUID-Technik verwenden, die erklärt wird), kann der Kunde auch verschiedene Fehler einführen, indem er einem neuen Gegenstand eine alte ID zuordnet (genau das habe ich mir überlegt, als ich 5 Sekunden nachgedacht habe) , es könnte eine Menge anderer Schlupflöcher geben).
Wie üblich sollte der Server ALLES erstellen und validieren , um Betrug zu verhindern .
quelle