Multiplayer, Bevy 0.18 und Fosdem
Hinweis: Dieser Blogpost wurde maschinell aus dem englischen Original übersetzt. Zum englischen Original.
Überblick
Diesen Monat ging es im Grunde ausschließlich darum, Multiplayer-Funktionalität einzubauen – mit einer kleinen Pause für die Bevy-0.18-Migration.
Wenn du das interessant findest und das Spiel spannend klingt, gib dem Spiel gern eine Wunschliste auf Steam. Das hilft enorm.
Ich muss sagen, ich bereue es, nicht früher mit dem Multiplayer-Code angefangen zu haben. Wie bei Internationalisierung und Speicherständen ist Multiplayer etwas, das man von Anfang an in die Architektur einplanen sollte. Die gute Nachricht: Der Code war sauber genug, dass der Refactor nicht allzu schmerzhaft war.
Ansonsten war die Migration von 0.17 auf 0.18 ziemlich unkompliziert. Ich musste ein paar weniger gepflegte Crates aufgeben, aber die eigentliche Migration war simpel.
Zu guter Letzt hab ich mir die Zeit genommen, zur Fosdem zu fahren, um die Bevy-Community zu treffen. Ich selbst hatte keinen Talk, aber Thierry Berger hat einen hervorragenden Vortrag über mobile Bevy-Spieleentwicklung gehalten.
Multiplayer
Leuten, die Spiele mit Bevy schreiben, hab ich bisher immer geraten, sich früh Gedanken über Internationalisierung, Gamepad-Unterstützung und Speicherstände zu machen. Jetzt bereue ich, dass ich den wahrscheinlich wichtigsten Faktor vergessen habe – nämlich Multiplayer und Netcode.
Dementsprechend meine aktualisierte Liste von Dingen, die man früh bedenken sollte:
- Multiplayer / Netcode
- Gamepad-Unterstützung
- Speicherstände
- Internationalisierung
All das nachträglich einzubauen ist nervig und schmerzhaft. (Fragt mich, woher ich das weiß! /s)
Exofactory-Spezifika
Exofactory ist ein Fabrikspiel, in dem man als KI spielt, die über kleine Roboter namens „Exoframes" mit der Welt interagiert. Diese müssen erst gebaut werden. Wenn man gerade keinen Exoframe steuert, kann man im globalen Kameramodus über die Fabriken fliegen.
Das ergibt einen ziemlich natürlichen kooperativen Ansatz: Neue Spielende können im globalen Modus beitreten, sich umschauen und bestehende Maschinen konfigurieren. Sobald ein Exoframe frei ist, kann man ihn „besetzen" und die Welt jenseits der Fabrik-Sensorreichweite erkunden und ausbauen.
Das führt zu einem schönen Multiplayer-Metaplot und gleichzeitig zu einer klaren technischen Aufgabenstellung für den Netcode:
- Im globalen Modus mit der Welt interagieren, einschließlich Bauen.
- Einen Exoframe aus einem Pool auswählen und steuern.
- Den Rest der Welt simulieren und die relevanten Komponenten aktualisieren.
- Sicherstellen, dass der Client die Welt korrekt sieht.
Für mich führt das ziemlich natürlich zu einem Server-autoritativen Modell. Die Server-Instanz des Spiels simuliert die Welt, und die Client-Instanzen nehmen einfach daran teil.
Bibliothek auswählen
Zum Zeitpunkt auf Bevy 0.18 scheint es zwei gut unterstützte Crates zu geben: bevy_replicon und lightyear.
Ich empfehle, sich beide anzuschauen – beide haben ihre eigenen Vorteile. Nach meinem (möglicherweise fehlerhaften) Verständnis bietet lightyear mehr Features wie Client-Side Prediction, deterministische Replikation und Interest Management (nur relevante Daten synchronisieren), allerdings mit mehr initialem Aufwand und Komplexität. Replicon lässt diese Features standardmäßig weg, ist dafür aber einfacher aufzusetzen mit weniger Entwicklungsaufwand. Falls ich hier falsch liege, korrigiere ich das gerne – meldet euch einfach.
Für Exofactory habe ich mich für das einfachere Replicon entschieden, weil das Spiel definitiv kein hektischer Shooter ist, mein geplantes Feature-Tempo eher gemächlich ist und ich bei Netcode noch relativ grün hinter den Ohren bin.
Das gesagt: Wenn die Spielarchitektur bereits gut strukturiert ist, dürfte ein späterer Wechsel kein allzu schmerzhafter Prozess sein.
Von Singleplayer zu Multiplayer
Im Kern macht Replicon zwei Dinge: Komponenten replizieren und Netzwerk-Events/Nachrichten an und von Clients verarbeiten.
Um Multiplayer zu ermöglichen, musste ich mehrere Systeme refactoren und logisch gruppieren.

Autoritative Kernsysteme
Diese laufen nur auf der Server-Instanz und aktualisieren die Welt (also alle Komponenten, die den Spielzustand speichern) für alles, was nicht direkt vom Spieler manipuliert wird.
Dazu gehören Dinge wie der Maschinenzyklus, der Eisenerz in Eisenbarren verwandelt, welche Sounds abgespielt werden sollen, und sogar die Abbaurate, die ein Exoframe hat, während man zuschaut. Es gibt noch viel mehr Systeme, aber das sind die typischen in dieser Gruppe.
Diese Systeme dürfen direkt in Komponenten schreiben. Replicon repliziert diese Änderungen automatisch zur Client-Instanz der Komponenten.
Player-UI-Systeme
Diese laufen nur auf Spielinstanzen, in denen tatsächlich jemand spielt. Sie spielen Sounds ab, zeigen die Bau-UIs an und informieren den Spieler über den Weltzustand. Diese Systeme lesen den Weltzustand, indem sie die lokalen Komponenten lesen, die automatisch synchron gehalten werden.
Der Teil, der den großen Refactor erforderte: In diesen Systemen ist keine direkte Manipulation von Komponenten erlaubt. Die Clients müssen ein Event/eine Nachricht an den Server schicken, der dann im Auftrag des Clients die Komponenten manipuliert und die Änderungen repliziert.
Netzwerk-Nachrichten & Events
Im obigen Diagramm hab ich nur ein Beispiel gezeigt, aber in Wirklichkeit passiert so ziemlich alles im Spiel über „Gucken" hinaus per Event oder Nachricht. Das gilt auch für den Spieler auf der Server-Instanz des Spiels.
Das ist meiner Meinung nach DER wichtigste Faktor, wenn man an einem Bevy-Spiel arbeitet, das irgendwann Multiplayer unterstützen soll. Hätte ich das von Anfang an so gemacht, wäre das Hinzufügen der Multiplayer-Funktionalität einfach gewesen. Auch wenn man anfangs nicht an Netzwerk denken möchte – allein sicherzustellen, dass alle Spieler-Manipulationen der Welt über die nativen Bevy-Event-Systeme oder Message-Systeme laufen, spart später enorm viel Zeit.
Auswirkungen & Ergebnisse

Es gab zwei interessante Nebeneffekte. Der erste war etwas, das ich eigentlich erst später angehen wollte, aber durch den Refactor deutlich einfacher wurde: eine Headless-Server-Instanz, die man per Docker/Podman etc. selbst hosten kann. So kann die Fabrik weiterlaufen, ohne dass jemand das Spiel auf dem PC offen halten muss.
Durch den Refactor und einen neuen Feature-basierten Build, der MinimalPlugins statt DefaultPlugins verwendet, bekommt man eine schlanke Headless-Server-Instanz, die so ziemlich überall laufen kann – sogar auf den meisten RISC-V-SBCs!
Das muss noch getestet werden, aber es sieht gut aus. Oben ist ein ähnliches Diagramm, aber für die Headless-Version des Spiels.
Der zweite interessante Nebeneffekt: Ich verwende deutlich weniger Bevy Resources, weil Replicon keine Resources repliziert. Stattdessen nutze ich viel mehr Pseudo-Singletons (also eine „leere" Entity, die nur die Komponente hat, die die Daten hält, die vorher in der Resource steckten).
Ich bin kein großer Fan von objektorientierten Design Patterns, also ist das schon etwas witzig und fühlt sich ein bisschen dreckig an.
Bevy-0.18-Migration
Ich hab das Licht gesehen! Nein wirklich – jedes Bevy-Spiel mit Beleuchtung sollte die Migration priorisieren. Da wurde richtig was gemacht, und das Spiel sieht merklich besser aus. Aber auch wenn euer Spiel kein Licht verwendet, solltet ihr trotzdem migrieren.
Abgesehen von ein paar Shader-Bind-Group-Sachen (also BindGroupLayout -> BindGroupLayoutDescriptor) und Atmosphere-Änderungen war es eine einfache Migration.
Schön zu sehen, dass der Release-Zyklus wieder im Takt ist.
Allerdings muss ich sagen: Mit jedem Upgrade sehe ich mehr Plugins, die auf der Strecke bleiben. Das lässt mich die Maintainer von Plugins umso mehr schätzen. Mit Bevys Release-Zyklus Schritt zu halten, ist im Vergleich zu jeder anderen Game Engine eine ordentliche Aufgabe.
Fosdem!
Apropos – ich hatte das Vergnügen, die Fosdem zu besuchen, ein Open-Source-Treffen, das jedes Jahr in Brüssel stattfindet.
Wenn ihr euch für Open-Source-Game-Engines interessiert – oder ehrlich gesagt für Open Source generell – kann ich nur empfehlen, hinzugehen. Es gibt massenhaft spannende Talks, aber das Beste (zumindest für mich) ist, die Leute zu treffen, mit denen man sonst nur online redet. Das Bevy-Abendessen mit Thierry Berger, Gee, Niklas Eicker, Firestar99 und einigen anderen netten Leuten war richtig gut.
Fazit
Ich dachte, ich krieg Multiplayer in einer Woche hin, aber es hat einen Monat gedauert – wie irgendwie erwartet. Ich bin ein besserer Spieleentwickler durch die Erfahrung. Man kann sich halt nicht für alles nur auf Backend-Patterns verlassen.
Die Bevy-0.18-Migration war unkompliziert.
Ich kann die Fosdem nur empfehlen, wenn ihr die Gelegenheit habt.