Diese Seite bietet einen Überblick über PaddleBallSO, das begleitende Demoprojekt zum E-Book „Erstellen Sie modulare Spielarchitekturen in Unity mit ScriptableObjects“, und erklärt, wie es Entwurfsmuster und Modularität in seiner Codearchitektur verwendet.
Dies ist der erste einer Reihe von sechs Mini-Leitfäden, die Unity-Entwicklern bei der Demo helfen sollen, die dem E-Book beiliegt. Die Demo ist von der Mechanik klassischer Arcade-Ball- und Schlägerspiele inspiriert und zeigt, wie Sie mithilfe von ScriptableObjects Komponenten erstellen können, die testbar, skalierbar und designerfreundlich sind.
Zusammen bieten das E-Book, das Demoprojekt und diese Mini-Anleitungen bewährte Methoden für die Verwendung von Programmierentwurfsmustern mit der ScriptableObject-Klasse in Ihrem Unity-Projekt. Diese Tipps können Ihnen dabei helfen, Ihren Code zu vereinfachen, den Speicherverbrauch zu reduzieren und die Wiederverwendbarkeit des Codes zu fördern.
Diese Serie umfasst die folgenden Artikel:
- Trennen Sie Spieldaten und Logik mit ScriptableObjects
- Verwenden Sie ScriptableObject-basierte Enumerationen in Ihrem Unity-Projekt
- Verwenden Sie ScriptableObjects als Delegatobjekte
- Verwenden Sie ScriptableObjects als Ereigniskanäle im Spielcode
- So verwenden Sie ein auf ScriptableObjects basierendes Laufzeitset
Bevor Sie sich in das ScriptableObject-Demoprojekt und diese Reihe von Mini-Anleitungen vertiefen, denken Sie daran, dass Entwurfsmuster im Kern nur Ideen sind. Sie sind nicht auf jede Situation anwendbar. Diese Techniken können Ihnen dabei helfen, neue Möglichkeiten der Arbeit mit Unity und ScriptableObjects zu erlernen.
Jedes Muster hat Vor- und Nachteile. Wählen Sie nur diejenigen aus, die Ihrem spezifischen Projekt wirklich nützen. Verlassen sich Ihre Designer stark auf den Unity Editor? Um ihnen die Zusammenarbeit mit Ihren Entwicklern zu erleichtern, könnte ein auf ScriptableObjects basierendes Muster eine gute Wahl sein.
Letztendlich ist die beste Code-Architektur diejenige, die zu Ihrem Projekt und Team passt.
Im Mittelpunkt von PaddleBallSO steht das klassische Spiel, das die Geburtsstunde moderner Videospiele markierte und mit zwei Spielern, zwei Schlägern und einem Ball gespielt wird.
Der Schwerpunkt liegt hier eher auf der Infrastruktur als auf der Spielmechanik. Betrachten Sie dies als „Spiel-Grundlage“ – die weniger glamouröse, aber lebenswichtige Grundlage, die Ihre Anwendung am Laufen hält.
Dieses Projekt konzentriert sich darauf, wie ScriptableObjects im Hintergrund arbeiten können, um eine einheitliche Anwendung zu erstellen. Verwenden Sie sie, um vielseitige Spielsysteme zu konstruieren, die die Projektwartung vereinfachen und die Wiederverwendbarkeit von Code fördern können. Sie können sie auch für Spielerdaten, Spielstatusverwaltung, Verhalten im Spiel und mehr verwenden.
Das PaddleBallSO- Projekt ist mit der neuesten Version von Unity Long Term Support (LTS) kompatibel, derzeit 2022 LTS. Es enthält das UI-Toolkit zum Erstellen einer Laufzeit-UI und das Eingabesystem zur Verarbeitung von Benutzereingaben.
Suchen und laden Sie das Projekt im GitHub-Repositoryherunter.
Laden Sie die Bootloader-Szene oder aktivieren Sie „Bootstrap-Szene beim Spielen laden“ über das GameSystems-Menü. Wechseln Sie zum Starten in den Wiedergabemodus.
Obwohl diese nicht spezifisch für ScriptableObjects sind, verwendet das Demoprojekt einige gängige Techniken, um die Spieleanwendung in einem konsistenten und vorhersehbaren Zustand zu starten.
Ein Scene Bootstrapper (oder Bootloader) ist ein Editor-Erweiterungsskript, das für die Einrichtung des Anfangszustands des Spiels verantwortlich ist. Dieser Initialisierungscode ist von der Spiellogik getrennt und stellt sicher, dass alle Abhängigkeiten für die Objekte in der Szene richtig eingerichtet sind.
Um Abhängigkeitsprobleme zu vermeiden, konfiguriert der Bootstrapper beim Laden einer Szene wichtige Spielobjekte, Manager oder Dienste.
Wenn Ihre Unity-Anwendung mehrere Szenen umfasst, kann der Bootloader das Laden einer bestimmten Bootstrap-Szene erzwingen, nämlich der ersten Szene aus den Build-Einstellungen. Beim Verlassen des Wiedergabemodus lädt der Editor die vorherige Szene neu.
Eine weitere Komponente in der Bootstrapszene, der Sequence Manager, kann dann beim Laden der Szene wichtige Prefabs instanziieren. In diesem speziellen Demoprojekt ist alles, was zum Erstellen des Spiels benötigt wird, ein Prefab, einschließlich einer Kamera, eines SplashScreen, UI-Menüs und eines SceneLoader.
Der SceneLoader lädt (und entlädt) dann je nach Bedarf alle Gameplay-Szenen additiv. In den meisten Fällen bestehen diese Szenen hauptsächlich aus Prefabs.
Projektszenen
Jedes Minispiellevel ist eine separate Unity-Szene und wird in den Build-Einstellungen angezeigt. Deaktivieren Sie den SceneBootstrapper im GameSystems-Menü, wenn Sie diese einzelnen Szenen erkunden möchten.
Viele Projekte beinhalten auch einen Staging-Bereich für das Hauptmenü nach der Bootstrap-Szene. In diesem vereinfachten Demoprojekt fehlt eine Hauptmenüszene.
Verwenden Sie die Menüs „Wiedergabe“ und „ Muster“ , um PaddleBallSOzu testen. Es umfasst:
- Designmusterdemos oder kurze Beispiele, die bestimmte Techniken zeigen und jedes Muster isoliert veranschaulichen
- Minispiele , die diese zu funktionalen, funktionierenden Beispielen kombinieren
Der Core- Ordner enthält nicht anwendungsspezifische Teile der Codebasis, wie die grundlegenden Musterskripte, die Szenenverwaltung und die UI-Logik. Dies sind allgemeinere Klassen, die für eine Vielzahl von Anwendungen genutzt werden könnten.
Das Beispielspiel stellt eine ikonische 2D-Physiksimulation nach und zeigt das Potenzial von auf ScriptableObjects basierenden Designmustern.
Bevor Sie sich jedoch in die Muster vertiefen, sollten Sie sich mit den MonoBehaviours vertraut machen, aus denen die Anwendung besteht. Wie zu erwarten, bestimmen Komponenten wie Paddle-, Ball-, Bouncer- und ScoreGoal-Skripte das grundlegende Gameplay.
Mehrere Manager-Skripte höherer Ebene steuern den Spielfluss:
- Der GameManger steuert die Spielzustände (Start, Ende, Zurücksetzen), initialisiert Spielkomponenten, verwaltet die Benutzeroberfläche und reagiert auf Ereignisse.
- Das GameSetup arbeitet mit dem GameManager zusammen, um Ball, Schläger, Wände und Tore einzurichten.
- Der ScoreManager aktualisiert Punktewerte, verarbeitet Spielevents und steuert UI-Updates für Punkteanzeigen.
Diese MonoBehaviours funktionieren mit Ihren ScriptableObjects. Sie spielen eine entscheidende Rolle bei der Überbrückung dieser Komponenten, sodass sie miteinander kommunizieren und Daten austauschen können.
Veranstaltungen sind für die Kommunikation zwischen verschiedenen Teilen des Projekts von entscheidender Bedeutung. Sie verbinden diese Manager-Skripte mit anderen Szenenobjekten und der Benutzeroberfläche. Diese ereignisgesteuerte Architektur kann dazu beitragen, den Code besser zu organisieren und leichter debuggen zu können.
Wir haben auch vereinfachte Demobeispiele für jedes der gängigsten ScriptableObject-Muster bereitgestellt. Wenn Sie sich mit ihnen vertraut machen, werden Sie erkennen, wie ScriptableObjects die Architektur des Minispiels unterstützen.
Wir hätten das vorgestellte Minispiel mit weitaus weniger Codezeilen erstellen können, aber diese Demo konzentriert sich speziell auf Designmuster mit ScriptableObjects. Beachten Sie, dass Sie viele dieser Muster auch ohne ScriptableObjects implementieren können.
Entscheiden Sie im Team, wie jedes Muster auf Ihr Projekt anwendbar ist, und wählen Sie den Ansatz, der für Sie am besten funktioniert.
Bei der Modularität der Softwareentwicklung geht es darum, eine Anwendung in kleinere, unabhängigere Teile aufzuteilen. Diese Module dienen bestimmten Zwecken und können separat entwickelt und getestet werden.
Jeder kleine Objektsatz funktioniert als eine Einheit und behandelt einen Aspekt des Spiels. Dabei kann es sich um alles Mögliche handeln, von der Steuerung der Spielereingaben über die Handhabung der Physik bis hin zur Punktezählung.
Achten Sie beim Durchsehen der Projektskripte auf die folgenden wichtigen Erkenntnisse:
- Konstruieren Sie Ihre Szenen aus Prefabs: Sie werden feststellen, dass die meisten Szenen im Projekt lediglich Sammlungen von Prefabs mit minimalen Überschreibungen sind. Prefabs bieten von Natur aus ein gewisses Maß an Modularität. Die Fehlerbehebung bei einer Funktion erfordert das isolierte Testen des jeweiligen Prefabs. Wie ScriptableObjects sind Prefabs Assets auf Projektebene, die wiederverwendet und in mehreren Szenen gemeinsam genutzt werden können.
- Verwenden Sie ScriptableObjects zur Datenspeicherung (und mehr): Vermeiden Sie die Verwendung von MonoBehaviours zum Speichern statischer Spieldaten. Nutzen Sie stattdessen ScriptableObjects für eine bessere Wiederverwendbarkeit. Sie können auch bestimmte Spiellogiken an ScriptableObjects delegieren oder diese die Kommunikation zwischen Ihren Szenenobjekten erleichtern lassen.
- Getrennte Anliegen: Sorgen Sie in Ihrem Projekt für eine klare Unterscheidung zwischen Daten, Logik und Benutzeroberfläche. Dies verbessert die Wartbarkeit des Codes und vereinfacht das Debuggen. Unser Menübildschirmsystem verwendet das neuere UI-Toolkit. Dieses UI-System erzwingt einen Workflow, der die Schnittstelle von der ihr zugrunde liegenden Logik trennt. Weitere Einzelheiten finden Sie im E-Book „Benutzeroberflächendesign und -implementierung in Unity“ .
- Abhängigkeiten minimieren: Durch die Reduzierung der Abhängigkeiten zwischen Komponenten können Sie Teile Ihres Projekts einfacher ändern oder ersetzen, ohne dass unvorhergesehene Probleme entstehen.
- Nutzen Sie Events zur Kommunikation: Ereignisse ermöglichen eine lose Kopplung zwischen Komponenten und ermöglichen ihnen, ohne direkte Abhängigkeiten Nachrichten aneinander zu senden. Sie können sie mit ScriptableObject-basierten „Ereigniskanälen“ weiter entkoppeln.
- Vermeiden Sie unnötige Singletons: Singleton-Entwurfsmuster können nützlich sein, aber nur, wenn eine einzelne Instanz einer Klasse wesentlich ist. Die übermäßige Verwendung von Singletons kann zu eng gekoppeltem Code führen und das Testen behindern. Überspringen Sie das Singleton, wenn es nicht benötigt wird.
Das Refactoring eines großen monolithischen Skripts in kleinere Teile fördert die Wiederverwendbarkeit und Skalierbarkeit. Dies führt zu einer verbesserten Zusammenarbeit im Team und vereinfachten Tests.
Wir haben das PaddleBallSO-Projekt erstellt, um Anwendungsfälle von ScriptableObject zu demonstrieren. Hier sind einige konkrete Orte, an denen Sie sie in Aktion sehen werden:
- Das GameDataSO ScriptableObject dient als zentraler Datencontainer für Spieleinstellungen. Bearbeiten Sie Ihre gemeinsamen Daten einmal und geben Sie sie dann an die anderen Objekte weiter, die sie benötigen.
- Die Minispiele sind auf zahlreiche Ereigniskanäle angewiesen, um entkoppelt kommunizieren zu können. Diese auf ScriptableObjects basierenden Ereignisse bilden das Rückgrat dafür, wie Objekte einander Nachrichten senden.
- Die Tonwiedergabe verwendet ein auf ScriptableObject basierendes Delegate-Objekt, um die Logik von der MonoBehaviour-Komponente zu trennen.
- Wir verwenden eine auf PlayerIDSO ScriptableObject basierende Aufzählung, um zwischen „Teams“ von Spieler1 und Spieler2 zu unterscheiden.
- Das LevelLayoutSO ScriptableObject dient als Datencontainer für die Startpositionen von Spielelementen wie Schlägern, Toren, Wänden und Bällen. Dies ermöglicht eine einfache Änderung der Level-Layouts innerhalb von Unity und extern über exportierte JSON-Dateien. Das Modifizieren von Leveldesigns außerhalb von Unity kann die Kreativität der Spieler und das Teilen benutzerdefinierter Layouts fördern.
Schauen Sie sich unbedingt auch die Designmuster-Demos an, um ein paar Extras zu erhalten!
Obwohl ScriptableObjects ein leistungsstarkes Tool zum Speichern von Spieldaten und Optimieren Ihres Arbeitsablaufs sein können, ist es wichtig, sie effektiv zu nutzen, um Ihr Projekt nicht zu überladen.
Hier sind einige Best Practices für die Verwendung von ScriptableObjects in Unity:
- Halten Sie die Daten modular und organisiert: Verwenden Sie separate ScriptableObjects für verschiedene Datentypen (z. B. eines für Spielerstatistiken, eines für das Verhalten des Feindes usw.). Teilen Sie komplexe Daten in kleinere, leicht zu handhabende Teile auf.
- Verwenden Sie Ordner und Namenskonventionen: ScriptableObjects können dazu beitragen, den Code in Ihren Skripten zu reduzieren, der Nachteil besteht jedoch darin, dass Sie mit mehr Assets in Ihren Projektordnern umgehen müssen. Eine ordnungsgemäße Benennung und Verzeichnisorganisation kann dabei helfen, diese ScriptableObjects effizient zu verwalten. Tipps zur Benennung finden Sie in unserem Code-Styleguide .
- Vermeiden Sie die übermäßige Verwendung von ScriptableObjects: ScriptableObjects sind erstaunliche Datencontainer, aber es ist wichtig, dass Sie sie nicht übermäßig verwenden. Bedenken Sie, dass ScriptableObjects die Komplexität Ihres Projekts erhöhen können. Setzen Sie sie daher nur ein, wenn sie einen klaren Vorteil bieten. (Verwenden Sie sie beispielsweise nicht zum Speichern persistenter Daten.)
- Sichern Sie Ihre Daten regelmäßig: Änderungen an ScriptableObjects erfolgen „live“ zur Laufzeit und werden als Asset-Dateien gespeichert. Sichern Sie Ihr Projekt regelmäßig, um Datenverlust zu vermeiden. Verwenden Sie eine Versionskontrollsoftware, um Änderungen an Ihren ScriptableObjects zu verfolgen.
- Verwenden Sie das Inspektorfenster: Ein wichtiger Vorteil von ScriptableObjects besteht darin, dass sie serialisierbar sind und im Inspector angezeigt werden. Nutzen Sie die Editor-Schnittstelle, um in ScriptableObjects gespeicherte Daten anzuzeigen und zu bearbeiten.
- Nutzen Sie benutzerdefinierte Editor-Skripte zu Ihrem Vorteil: ScriptableObjects können nicht nativ auf Laufzeitobjekte aus der Szenenhierarchie verweisen. Verwenden Sie Editor-Skripting, um den Inspector benutzerfreundlicher zu gestalten, wenn Sie diese Objekte visualisieren müssen.
Durch Befolgen dieser Richtlinien können Sie häufige Entwicklungsfehler vermeiden.
Lesen Sie mehr über Entwurfsmuster mit ScriptableObjects im E-Book „Erstellen Sie modulare Spielearchitektur in Unity mit ScriptableObjects“. Weitere Informationen zu gängigen Entwurfsmustern für die Unity-Entwicklung finden Sie auch im E-Book „Verbessern Sie Ihren Code mit Spielprogrammiermustern“.