Benutzer gegen Spielermodell

7

Viele der Online-Spiele haben dieses Konzept von "Benutzer" oder "Profil" und das Konzept von "Spieler". Der "Benutzer" hat einen Benutzernamen, ein Passwort, Lebenszeitstatistiken usw. Das Spielerkonzept ist spielbasiert und enthält flüchtige Informationen zum aktuell gespielten Spiel. Zumindest stelle ich mir das so vor.

Ich bin verwirrt darüber, wie das normalerweise umgesetzt wird. Enthält die Player-Klasse einen Zeiger auf das User-Objekt oder erbt sie vom User? oder vielleicht noch etwas?

Ich kann die beiden nicht vollständig entkoppeln, da ich während des Spiels Nachrichten zwischen "Benutzer" und "Spieler" hin und her senden muss (z. B. Aktualisierungserfolge).

Mazyod
quelle

Antworten:

13

Sie werden normalerweise nicht einmal von derselben Maschine verarbeitet, geschweige denn von derselben Codebasis. Das Benutzerprofil wird von einem Dienst übergeben, der sich nur mit Benutzern befasst. Der Simulationsserver kümmert sich um Dinge im Spiel. Möglicherweise gibt es sogar einen anderen Sitzungsserver, der die beiden miteinander verbindet.

Der Simulationsserver verfügt über eine ID, die jedem Benutzer entspricht. Die PlayerKlasse sieht also möglicherweise folgendermaßen aus:

struct Player {
  UserId _user;
  PlayerId _player;
  int _health;
  // etc.
};

Für alles, was das Benutzerkonto betrifft, sendet der Server eine Nachricht an den Benutzerdienst, in der er darüber informiert, was passiert ist, z

struct UserAchievementMessage : public UserMessage {
  UserId _user;
  AchievementId _achievement;
  uint64 _timestamp;
  // etc.
};

Wenn der Benutzer eine Leistung für etwas im Spiel erzielt, teilt der Simulationsserver dem Benutzerdienst lediglich dies mit (normalerweise über eine Art Messaging-Dienst, z. B. RabbitMQ oder dergleichen), und vergisst dies dann (da dies nicht die Aufgabe des Simulationsservers ist sich um Benutzer kümmern).

Wenn der Benutzerdienst Spiele im Spiel benachrichtigen muss, kann er erneut einen Nachrichtendienst (oder einen Proxy über einen Spieldienst) verwenden, um Spielerinstanzen dieses Benutzers über Änderungen zu informieren. Beispielsweise kennt der Match-Service alle laufenden Matches, wer an diesen Matches teilnimmt usw., sodass ein Benutzerdienst den Match-Service einfach auffordern kann, alle Simulationsserver zu benachrichtigen, auf denen eine Instanz dieses Benutzers (eines Spielers) vorhanden ist das hat sich geändert. Durch die geschickte Verwendung von RabbitMQ oder dergleichen kann auch die Notwendigkeit eines Proxy-Dienstes entfallen.

Samller / einfachere Spiele haben oft nur einen oder zwei Server und überlappen viele Funktionen. Dies liegt jedoch an Zeit- / Budgetmangel und nicht an guter Technik.

In jedem Fall Userund Player(oder was auch immer Sie verwenden) sind zwei völlig getrennte Dinge. Die Kupplung sollte, falls vorhanden, so leicht wie möglich sein. Eindeutige IDs sind normalerweise der richtige Weg. Jeder Benutzer kann beispielsweise eine UUID haben, und jede PlayerInstanz enthält nur diese UUID. Wenn sich etwas auf a Playerauswirkt User, rufen Sie eine Methode auf oder senden Sie eine Nachricht UserManagermit der betroffenen UUID und anderen Details an. Sie UserManagerkönnen dann interne Datenstrukturen aktualisieren, Netzwerknachrichten senden oder andere Implementierungsdetails ausführen, die erforderlich sind.

Sean Middleditch
quelle
Mindblown ... Ich habe in der von Ihnen beschriebenen Größenordnung nicht einmal darüber nachgedacht, eher wie ein lokales Spiel mit Minispielen. Trotzdem gilt das Konzept.
Mazyod