Godot 4 ist auf dem Weg zum ersten Release Candidate. Der Unterschied zwischen Godot 3.x und Godot 4 ist gewaltig. Während es schon diverse Tutorials zu vielen der Änderungen gibt, kommt es mir so vor, als ob der Bereich der Netzwerkprogrammierung vernachlässigt wurde und das, obwohl, oder vielleicht weil, es dort auch eine Menge Änderungen gab. Dazu kommt, dass mich dieser Teil besonders interessiert, da es bislang fast nur pure Multiplayer-Spiele geschafft haben, mich längere Zeit zu fesseln und ich in diesem Bereich meine berufliche Erfahrung gut mit einbringen kann.
Da das Thema so umfangreich ist, dass sich darüber wahrscheinlich auch ein Buch schreiben ließe, werde ich es im Rahmen einer Tutorialserie behandeln. Die folgende Liste zeigt alle bislang erschienenen Artikel dieser Serie:
- Netzwerktutorial 1: Allgemeines und Übersicht
- Netzwerktutorial 2: Das "gehende Skelett"
- Netzwerktutorial 3: Login 1 - Der Game-Client
- Netzwerktutorial 4: Login 2 - Gateway- und Authentication-Server
- Netzwerktutorial 5: Login 3 - World-Server
- Netzwerktutorial 6: Verschlüsselte Verbindungen mit Hilfe von DTLS
Übersicht
Diese Tutorialserie ist dazu gedacht, einen Einstieg in das Thema Netzwerkprogrammierung mit Godot 4 zu bekommen. Aus diesem Grund wird alles, was im Rahmen dieser Serie erstellt wird, mit der aktuellen Godot 4 Version erstellt, auch wenn dies in der Realität nicht unbedingt der Fall sein wird, da es für bestimmte Aufgaben bessere Technologien gibt. Bevor es aber im nächsten Artikel mit der Praxis losgeht, möchte ich hier zuerst über einige Themen sprechen, die die gewählte Architektur beeinflussen, um anschließend die von mir angestrebte Architektur vorzustellen.
Wenn man ohne jegliche Vorerfahrungen über das Thema Server-Architektur für reine Multiplayer-Spiele nachdenkt, kommt man wohl zuerst auf eine solche Idee:

Spieleclients können direkt mit dem einzigen dedizierten Spielserver via Internet kommunizieren.
Möglicherweise wird bei diesen ersten Überlegungen noch daran gedacht, dass der dedizierte Server eventuell noch eine Datenbank benötigt, aber das ist aktuell nur ein kleines Detail. Es gibt mit einem einzelnen dedizierten Server sicherlich viele Probleme, die größten sind meiner Meinung nach aber:
- Sicherheit
- Skalierbarkeit
Die Server-Architektur für reine Multiplayer-Spiele muss zumindest zwei Aufgaben erfüllen: Neue Clients authentifizieren und anschließend die spielrelevante Kommunikation mit allen Clients übernehmen. Für die Authentifizierung werden Benutzerdaten benötigt, die auf gar keinen Fall in falsche Hände gelangen sollten, aber in diesem Fall auf einem Server liegen, der direkt ans Internet angeschlossen ist. Zumal der Zugriff nicht auf bestimmte IP-Adressen eingeschränkt werden kann, da dadurch potentielle Spieler abgewiesen werden würden. Von nicht vorhandener Ausfallsicherheit muss man in diesem Szenario ja erst gar nicht anfangen zu sprechen. Wenn der Server nicht verfügbar ist, ist weder der Multiplayer verfügbar noch sind die Spieler in der Lage, ihre Benutzerdaten zu ändern.
Die Anzahl möglicher Spieler ist generell von verschiedenen Faktoren abhängig, worauf ich im nächsten Abschnitt näher eingehen werde, aber eine gewisse Obergrenze ist allgegenwärtig. Möchte man also die Grenze nach oben verschieben, so werden mehrere Server benötigt und dabei sollte auch nicht jeder Server alle Benutzerdaten speichern.
Mögliche Bottlenecks
Es gibt verschiedene Faktoren, die Einfluss auf die Anzahl gleichzeitig verbundener Spieler pro Server haben:
- Maximale Anzahl gleichzeitig verbundener Spieler
- Requests pro Sekunde (RPS)
- Spieleranzahl, die sinnvoll auf der Spielwelt/der Map untergebracht werden kann
Bei der Nutzung von ENet mit Godot gibt es eine Obergrenze von 4095 gleichzeitigen Verbindungen, was bedeutet, dass mehr Spieler pro Server erst einmal nicht möglich sind. Sollte man dennoch mehr als ~4k Spieler zeitgleich in einer Spielwelt unterstützen wollen, muss man die Spielwelt auf mehrere Server verteilen. Dazu wird die Spielwelt in Zonen unterteilt und diese Zonen auf die Server verteilt. Im Optimalfall wird diese Verteilung abhängig von der jeweiligen Auslastung dynamisch zur Laufzeit vorgenommen, um Ressourcen zu sparen. Aber durch die Aufteilung auf mehrere Server steigt die bereits hohe Komplexität nochmal deutlich an, da man Lösungen entwickeln muss, um Spielern Serverwechsel bspw. beim Zonenwechsel zu ermöglichen, im Optimalfall, ohne dass die Spieler dies bemerken. Aber das Thema ist so komplex, dass es eigene Artikel rechtfertigt.
Die notwendige Anzahl von Requests pro Sekunde (RPS) ist abhängig vom gewählten Genre. In schnellen und interaktionsreichen Genres wie bspw. Ego-Shootern ist es essentiell, möglichst viele RPS zu haben, damit alle Spieleclients ihre notwendigen Spieldaten (z.B. eigene Position, Positionen der Mitspieler, Positionen “sichtbarer” Gegner) so schnell wie möglich bekommen, um sie annähernd verzögerungsfrei darzustellen, sodass der Spieler reagieren kann. Für Spiele wie z.B. FarmVille ist es auch ausreichend, nur wenige RPS zu haben, da einerseits der Multiplayer meines Wissens nur wenig benutzt wird und andererseits es nicht so spielrelevant ist, wo genau sich Besucher der eigenen Farm gerade befinden. Natürlich ist die Anzahl realistisch zu erreichender RPS auch davon abhängig, wie aufwendig die serverseitigen Berechnungen sind und wieviel Rechenkapazität verfügbar ist.
Um Spielern eine gute Spielerfahrung zu ermöglichen, sollte die Spieleranzahl an die Mapgröße, das Genre und die zentralen Spielmechaniken angepasst sein. Bei kompetitiven Spielen sollte die Kartengröße groß genug sein, dass gegnerische Spieler(teams) nicht direkt beieinander spawnen, aber klein genug, dass gegnerische Spieler(teams) dennoch zeitnah aufeinandertreffen. Bei Hunt:Showdown ist eine zentrale Spielmechanik, dass eigentlich alles in der Spielwelt Geräusche verursacht, die dank 3D Spatial Audio gut lokalisiert werden können, daher versuchen viele Spieler, möglichst lange verdeckt zu agieren. Um dieser Spielmechanik gerecht zu werden, ist die Map mit 1 Quadratkilometer für maximal 12 Spieler aufgeteilt in durchschnittlich 6 Teams sehr spärlich von Spielern “bevölkert”. In (M)MORPGs ist die Welt zwar meist auf Hunderte bis Tausende von Spielern ausgelegt, aber trotz allem kommt es auch dabei immer zu Situationen, wo bestimmte Gebiete komplett überlaufen sind, sodass an Questen dann nicht zu denken ist. Jeder, der bei einem Livegang einer WoW-Erweiterung spielen wollte, weiß, was ich damit meine.
Die im Tutorial angestrebte Architektur

Die Spieleclients besorgen sich über den Gateway beim Authentication Server ein Token, welches sie benötigen, um Kontakt zum World Server aufzubauen.
Das Bild veranschaulicht die Architektur, die im Lauf dieser Tutorialserie erstellt werden soll. Sie besteht aus drei verschiedenen Arten von Servern:
- Gateway Server
- Schützt den Authentication Server vor direkten Zugriffen aus dem Internet und leitet nur valide Anfragen an den Authentication Server weiter.
- Authentication Server
- Besitzt Zugriff auf die Benutzerdaten, um Logindaten validieren zu können und stellt bei validen Logindaten ein Token für den Zugriff auf die World Server aus.
- World Server
- Validiert ausgestellte Tokens und stellt das eigentliche Spiel bereit. In diesem Beispiel besitzt jeder World Server eigene Spielerdaten, d.h. es handelt sich dabei um ein Spiel mit persistenten Daten bspw. ein (M)MORPG.
Neben der Architektur kann man in dem Bild auch die Kommunikation erkennen:
- Der Spieleclient schickt die Login-Daten an einen der Gateway Server
- Der Gateway Server leitet die Login-Daten an den Authentication Server weiter, welcher sie dann überprüft
- Das Resultat wird an den Gateway Server gesendet:
- Im Positivfall ein Token
- Im Negativfall ein Fehlercode
- Der Gateway Server leitet das Resultat an den Spieleclient weiter
- Wenn der Spieleclient ein Token bekommen hat, sendet er den Token an den gewünschten World Server weiter
- Der World Server validiert den Token und sollte er gültig sein, beginnt das eigentliche Spiel
Diese Architektur bildet meiner Meinung nach eine gute Möglichkeit die Netzwerkprogrammierung mit Godot 4 zu lernen und zu verstehen. Das eigene Spiel wird sicherlich andere Anforderungen haben, aber so hat man eine gute Grundlage, um sie dann an die eigenen Bedürfnisse anzupassen.