Wie kann ich Entity-IDs in einem Netzwerkspiel zuverlässig zuweisen?

17

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!

Lucas
quelle
1
Warum haben nicht alle Kunden die gleichen Entitäten? Sind die Clients nicht synchronisiert? Oder ist es eine große Welt, in der die Kunden nicht alle das gleiche Spiel ausführen?
Philip
2
Meine bisherige Architektur folgt der der UE3 (mehr Infos hier ). Grundsätzlich wissen Kunden nur über Entitäten Bescheid, die sich in ihrer Nähe auf der Welt befinden. Außerdem werden die Clients nicht im Sperrschritt ausgeführt, sondern der Server steuert den größten Teil der Logik und kann die Clientdaten jederzeit überschreiben. Ich denke jetzt, da ich darüber nachdenke, konnte ich dem Server nur erlauben, Entitäten zu erstellen und Clients dazu zu bringen, RPC zu verwenden, um dies zu tun. Ich bin mir nicht sicher, wie ich am besten vorgehen soll. Ich bin ein Grafikprogrammierer bei Tag :)
Lucas
1
Ich denke, wie Sie sagen, sollte es nur vom Server gehandhabt werden, wenn dies in Ihrer gegebenen Architektur überhaupt machbar ist. Bewahren Sie dann einen Stapel freier Entitäts-IDs getrennt von der Entitätsliste / -zuordnung auf, damit Sie wissen, welche IDs verfügbar sind. Wenn ein autorisierendes Servermodell ausfällt, sollte Ihr Ranging-Ansatz in Bezug auf Bereiche in Ordnung sein. Vier Milliarden sind eine Menge, sogar um sich unter 4000 Spielern in einem MMO zu verteilen. Verwenden Sie dann den gleichen Ansatz, um die verfügbaren IDs zu verfolgen wie bei einer Authentifizierung. Server.
Ingenieur
@Lucas, Ihr Link sagt "Der Server identifiziert die Menge der" relevanten "Akteure für jeden Client". Dies impliziert, dass der Server alle Entitäten kennt und in der Lage ist, sie aufzulisten.
Kylotan
1
Sicher, aber was ist, wenn ein Client eine neue Entität A erstellt, aber bevor er die Erstellungsnachricht erhält, erstellt der Server die neue Entität B, und beide erhalten dieselbe "freie" ID.
Lucas

Antworten:

13

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.

John McDonald
quelle
Danke für all die guten Infos Jungs! Ich ging schließlich mit dem Server erstellt alle Entitäten Ansatz, aber wenn ich finde, dass zu viel Latenz einführt, werde ich Trevor-Methode versuchen.
Lucas
Für clientspezifische IDs (für die Vorhersage beim Warten auf den Server erforderlich) können Sie einfach ein Präfix für die ID verwenden.
Danijar
6

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. ;)

Trevor Powell
quelle
Das ist eine gute Idee für den Umgang mit Überlauf. Einfach, aber ich habe nicht daran gedacht :). Das "Vergessen" all Ihrer Entitäten ist nett, da im Grunde derselbe Codepfad wiederverwendet werden kann, den der Client verwendet, wenn er sich dem Spiel anschließt
Lucas,
4

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:

entityId = clientId<<24 + (maxEntityIn++)

oder so.

Und wenn ich mich irre und Sie einen autorisierenden Server haben, erstellen Sie niemals neue Entitäten auf Clients.

Keine Ursache
quelle
1

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 .

Valmond
quelle