Unity durchsuchen

3 coole Wege, Ihr Spiel mit scriptfähigen Objekten aufzubauen

Last updated: December 2018

Was Sie von dieser Seite mitnehmen: Eine Einsatzbereite Anleitung, wie Sie Ihren Gamecode leicht managen, ändern und debuggen können, wenn Sie ihn mit skriptfähigen Objekten erstellen.

Diese Tipps stammen von Ryan Hipple, leitender Techniker bei Schell Games. Er hat eine Menge Erfahrung in der Anwendung von scriptfähigen Objekten zum Gestalten von Videospielen. Sie können sich hier Ryans Unite-Vortrag über skriptfähige Objekte ansehen; wir empfehlen auch, sich die Session von Unity-Techniker Richard Fine für eine tolle Einführung zum Thema "Scriptfähige Objekte" anzuschauen. Vielen Dank, Ryan!

Kurz gefasst: Was sind scriptfähige Objekte?

ScriptableObject ist eine serialisierbare Unity-Klasse, die Ihnen ermöglicht, große geteilte Datenmengen unabhängig von Script-Instanzen zu speichern. Die Verwendung von scriptfähigen Objekten erleichtert die Änderungsverwaltung und das Debugging. Sie können eine Stufe der flexiblen Kommunikation zwischen den verschiedenen Systemen in Ihrem Spiel erstellen, sodass es insgesamt unkomplizierter ist, Dinge im Verlauf der Erstellung zu ändern und anzupassen und Komponenten wiederzuverwenden.

Drei Säulen des cleveren Game-Engineering

Halten Sie die Dinge modular ...

  • Vermeiden Sie, Systeme zu erstellen, die direkt voneinander abhängen. Ein Inventarsystem sollte beispielsweise mit den anderen Systemen in Ihrem Spiel kommunizieren können, aber Sie sollten keine harte Referenz zwischen ihnen erstellen, da dies die erneute Umsetzung von Systemen in verschiedene Konfigurationen und Beziehungen erschwert.
  • Erstellen Sie Szenen als "saubere Neuanfänge": vermeiden Sie transiente Daten zwischen Ihren Szenen. Für jede neue Szene sollte es einen klaren Bruch und einen Ladevorgang geben. Das ermöglicht Ihnen Szenen, die ein einzigartiges Verhalten aufweisen, das in anderen Szenen nicht vorhanden ist, ohne dass Sie einen Hack machen müssen.
  • Stellen Sie Prefabs so ein, dass sie selbständig arbeiten. Soweit möglich, sollte jedes Prefab, das Sie in einer Szene platzieren, diese Funktionalität aufweisen. Dies ist für größere Teams hinsichtlich der Source Control äußerst hilfreich, wobei Szenen eine Liste von Prefabs sind und die Prefabs die individuelle Funktionalität beinhalten. So finden die meisten Check-Ins auf dem Prefab-Level satt, was zu weniger Konflikten in der Szene führt.
  • Konzentrieren Sie jede Komponente auf die Lösung eines einzelnen Problems. Das macht es einfacher, mehrere Komponenten zusammenzufügen, um etwas Neues zu erstellen.

... editierbar

  • Machen Sie in Ihrem Spiel so viel wie möglich datengesteuert: Wenn Sie Ihre Spielsysteme wie Maschinen erstellt haben, die Daten als Anweisungen verarbeiten, können Sie sogar effizient Änderungen am Spiel vornehmen, wenn es ausgeführt wird.
  • Wenn Ihre Systeme so modular und komponentenbasiert wie möglich eingerichtet sind, vereinfacht das die Bearbeitung, auch für Ihre Grafiker und Desigern. Wenn Designer im Spiel Dinge zusammenfügen können, ohne nach einer bestimmten Funktion fragen zu müssen – größtenteils dank der Implementierung von kleinen Komponenten, die jeweils nur eine Funktion ausführen – haben sie die Möglichkeit, solche Komponenten auf verschiedene Art und Weise zu kombinieren, um ein neues Gameplay/Mechaniken zu finden. Ryan sagt, dass einige der coolsten Merkmale seines Spiels, an denen sein Team gearbeitet hat, durch diesen Prozess entstanden sind, den er "Emergent Design" nennt.
  • Es ist entscheidend, dass Ihr Team Änderungen am Spiel zur Laufzeit durchführen kann. Je mehr Änderungen Sie zur Laufzeit durchführen können, desto eher finden Sie Balance und Werte und wenn Sie Ihren Laufzeit-Status zurückspeichern können, wie es mit scriptfähigen Objekten möglich ist, sind sie in einer guten Position.

... und Debug-fähig

Dies ist eher eine "Untersäule" der ersten beiden. Je modularer Ihr Spiel aufgebaut ist, desto einfacher ist es, einzelne Bereiche davon zu testen. Je editierbarer Ihr Spiel ist, das heißt, je mehr Funktionen darin über eine eigene Inspector-Ansicht verfügen, desto einfacher ist das Debugging. Stellen Sie sicher, dass Sie den Debug-Status im Inspector sehen können und betrachten Sie niemals eine Funktion als fertig, bis Sie einen Plan haben, wie Sie sie debuggen können.

Ryans "Top-3-Tipps" für die Erstellung mit scriptfähigen Objekten

Variablen

Eine der einfachsten Sachen, die Sie mit einem scriptfähigen Objekt erstellen können, ist eine selbständige, Asset-basierte Variable. Hier sehen Sie beispielhaft eine FloatVariable, die Erläuterung trifft aber auch auf jeden anderen serialisierbare Variablentyp zu.

Unity – skriptfähiges Objekt – FloatVariable

Damit kann jeder in Ihrem Team, unabhängig von den jeweiligen technischen Kenntnissen, durch die Erstellung eines neuen FloatVariable-Assets eine neue Spielvariable definieren. Jede MonoBehaviour und jedes ScriptableObject kann eine öffentliche FloatVariable statt eines "Public Float" verwenden, um auf diesen neuen, geteilten Wert zu referenzieren.

Sogar noch besser: Wenn ein MonoBehaviour den Wert einer FloatVariable ändert, können andere MonoBehaviours diese Änderung sehen. Dadurch entsteht eine Art Messaging-Ebene zwischen Systemen, die keine Referenzen zueinander benötigen.

Ein Anwendungsbeispiel hierfür sind die Gesundheitspunkte (HP) eines Spielers. In Spielen mit einem einzelnen lokalen Spieler können die HP des Spielers eine FloatVariable namens PlayerHP sein. Wenn der Spieler Schaden nimmt, wird "PlayerHP" geringer. Heilt sich der Spieler, vergrößert sich "PlayerHP".

Stellen Sie sich jetzt ein Gesundheitsleisten-Prefab in der Szene vor. Die Gesundheitsleiste überwacht die PlayerHP-Variable, um ihre Anzeige zu aktualisieren. Ohne eine Codeänderung könnte sie einfach auf etwas anderes hinweisen, beispielsweise eine PlayerMP-Variable. Die Gesundheitsleiste weiß nichts über den Spieler in der Szene, sie liest nur von derselben Variable ab, auf die der Spieler schreibt.

Unity – skriptfähiges Objekt handhabt Spielertod

Sobald wir so eingerichtet sind, ist es einfach, weitere Dinge hinzuzufügen, um die PlayerHP im Auge zu behalten. Das Musiksystem kann sich ändern, wenn die PlayerHP sinkt, Feinde können ihre Angriffsmuster ändern, wenn sie wissen, dass der Spieler schwach ist, Screen-Space-Effekte können die Gefahr des nächsten Angriffs unterstreichen. Wichtig hierbei ist, dass das Player-Skript keine Nachrichten an diese Systeme sendet und diese Systeme nichts über das Spieler-Game-Object wissen müssen. Sie können auch den Inspector aufrufen, wenn das Spiel läuft, und den Wert der PlayerHP ändern, um Dinge zu testen.

Wenn Sie den Wert einer FloatVariable ändern, könnte es ratsam sein, Ihre Daten in einen Runtime-Wert zu kopieren, um nicht den Wert zu verändern, der auf der Festplatte für das ScriptableObject gespeichert ist. Wenn Sie dies tun, sollten MonoBehaviours auf RuntimeValue zugreifen, um eine Bearbeitung des auf der Festplatte gespeicherten InitialValue zu vermeiden.

Unity – skriptfähiges Objekt – FloatVariable

Events

Eins meiner Lieblings-Features, das zusätzlich zu scriptfähigen Objekten erstellt werden kann, ist ein Event-System. Event-Architekturen helfen dabei, Ihren Code zu modularisieren, indem sie Nachrichten zwischen Systemen versenden, die nicht in direkter Verbindung zueinander stehen. Sie ermöglichen Reaktionen auf Zustandsänderungen, ohne den Zustand ständig in einem Update-Loop zu überwachen.

Dieses Event-System besteht aus zwei Teilen: einem GameEvent ScriptableObject und einer GameEventListener MonoBehaviour. Designer können eine beliebige Anzahl von GameEvents im Projekt erstellen, um wichtige Nachrichten zu repräsentieren, die gesendet werden können. Ein GameEventListener wartet auf das Auftreten eines speziellen GameEvents und reagiert mit dem Aufruf eines UnityEvent (was kein "echtes" Event ist, sonder eher ein serialisierter Funktionsaufruf).

Unity – skriptfähiges Objekt – Game-Event-Listener

Unity – skriptfähiges Objekt – Game-Event-Listener

Unity – skriptfähiges Objekt – Game-Event-Listener

Ein Beispiel hierfür ist der Tod eines Spielers im Spiel. Dies ist ein Punkt, wo sich sehr viel bei der Ausführung ändern kann, es aber schwierig ist festzulegen, wo die ganze Logik gecodet sein soll. Soll das Player-Script das "Game Over"-UI auslösen, eine Änderung in der Musik? Sollten Feinde in jedem Frame überprüfen, ob der Spieler noch am Leben ist? Ein Event-System hilft uns, diese problematischen Abhängigkeiten zu vermeiden.

Wenn der Spieler stirbt, ruft das Player-Script "Raise" für das OnPlayerDied-Event auf. Das Player-Script muss nicht wissen, welches System sich darum kümmert, es überträgt nur. Das Game-Over-UI hört auf das OnPlayerDied-Event und beginnt mit der Animation, ein Kamera-Script kann darauf hören und das Bild ausblenden und ein Musiksystem kann mit einer Änderung der Musik reagieren. Wir können jeden Feind auf OnPlayerDied hören lassen und eine Verspotten-Animation oder eine Statusänderung zu einem inaktiven Verhalten auslösen.

Dieses Muster macht es unglaublich einfach, neue Reaktionen auf den Tod eines Spielers hinzuzufügen. Außerdem ist es einfach, diese Reaktionen durch den Aufruf von "Raise" über einen Test-Code oder eine Schaltfläche im Inspector zu testen.

Unity – skriptfähiges Objekt handhabt Spielertod

Das Event-System, das ich bei Schell Games erstellt habe, ist zu etwas Komplizierterem angewachsen und beinhaltet Funktionen, die Passing Data und Auto-Generating-Types zulassen. Ich kann hier nicht alle Einzelheiten erläutern, aber dieses Beispiel war im Wesentlichen der Ausgangspunkt von dem, was wir heute benutzen.

Systeme

Scriptfähige Objekte müssen nicht nur einfach Daten sein. Sehen Sie sich jedes System an, das Sie in eine MonoBehaviour implementieren und überlegen Sie, um Sie die Implementierung stattdessen in ein ScriptableObject verschieben können. Versuchen Sie, statt einen InventoryManager auf einer DontDestroyOnLoad MonoBehaviour zu verwenden, ein ScriptableObject einzusetzen.

Da es nicht an die Szene gebunden ist, hat es keinen Transform und erhält keine Update-Funktionen, aber es behält den Status zwischen dem Laden der Szenen ohne besondere Initialisierung bei. Verwenden Sie anstelle eines Singletons eine öffentliche Referenz auf Ihr Inventar-Systemobjekt, wenn ein Skript auf das Inventar zugreifen muss. Dadurch ist es einfacher, ein Test- oder Tutorial-Inventar einzubauen, als wenn Sie ein Singleton verwenden würden.

Stellen Sie sich hierzu ein Player-Script vor, das auf das Inventarsystem verweist. Wenn der Spieler spawnt, kann es im Inventar nach allen Besitztümern fragen und jedes Ausrüstungsstück spawnen. Das Ausrüstung-UI kann ebenfalls auf das Inventar referenzieren und die Gegenstände durchgehen, um zu bestimmen, welche ausgewählt werden sollen.

Weitere Ressourcen

Wir wollen es wissen! Haben Ihnen diese Inhalte gefallen?

Ja, weiter so. Na ja. Könnte besser sein.

Unity Buffbot macht Ihnen die Arbeit leichter

Melden Sie sich an, um wöchentlich technisches und kreatives Know-how von Unity-Experten zu erhalten.

Abonnieren
Alles klar

Wir verwenden Cookies, damit wir Ihnen die beste Erfahrung auf unserer Website bieten können. Klicken Sie hier für weitere Informationen.