
Verwenden Sie ScriptableObjects als Ereigniskanäle im Spielcode
Diese Website wurde aus praktischen Gründen für Sie maschinell übersetzt. Die Richtigkeit und Zuverlässigkeit des übersetzten Inhalts kann von uns nicht gewährleistet werden. Sollten Sie Zweifel an der Richtigkeit des übersetzten Inhalts haben, schauen Sie sich bitte die offizielle englische Version der Website an.
Wie sorgen Sie dafür, dass unterschiedliche Systeme in Ihrer Anwendung zusammenarbeiten? Eine gängige Lösung besteht darin, ein Ereignis zum Senden von Nachrichten zwischen Objekten zu verwenden. Lesen Sie weiter, um zu erfahren, wie Sie ScriptableObjects als Ereigniskanäle in Ihrem Unity-Projekt verwenden.
Dies ist der fünfte in einer Reihe von sechs Mini-Leitfäden, die Unity-Entwicklern bei der Demo helfen sollen, die dem E-Book „Erstellen Sie modulare Spielarchitekturen in Unity mit ScriptableObjects“beiliegt.
Die Demo ist von der Mechanik klassischer Arcade-Ball- und Paddelspiele 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:
Wichtiger Hinweis bevor Sie beginnen
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.
Lose Kopplung, hohe Kohäsion
Beim Erstellen verschiedener Module oder Systeme in einer Anwendung ist es oft hilfreich, sich diese als „Code-Inseln“ vorzustellen. Jedes Modul kann mehrere Komponenten oder GameObjects haben, die für einen gemeinsamen Zweck zusammenarbeiten.
Beispielsweise kann der Schläger des Spielers ein Skript enthalten, das die Eingaben des Spielers interpretiert, eines, das Bewegungen oder Kollisionen handhabt usw. Wenn zwischen diesen Teilen Abhängigkeiten bestehen, können Sie den Inspector verwenden, um diese engen Verbindungen herzustellen.
Bedenken Sie jedoch, dass jedes Mal, wenn Sie einem anderen Objekt eine Abhängigkeit hinzufügen, ein geringes Risiko besteht. Wenn möglich, sollten Sie diese Abhängigkeiten von externen Objekten minimieren. Die Kommunikation mit Dingen außerhalb Ihres Moduls oder Systems wird nicht so direkt sein.
Sie könnten das Paddle-Skript so konfigurieren, dass es auf den Ball in Ihrem Spiel verweist, das bedeutet aber, dass eine Verbindung besteht. Sobald sie durch eine Abhängigkeit miteinander verbunden sind, könnte eine Änderung an einem davon möglicherweise auch die andere beeinflussen.
Idealerweise möchten Sie einen Teil der Anwendung ändern können, ohne dass andere Dinge beschädigt werden. Das Ziel besteht darin, Ihre Module intern zusammenhängend, aber extern entkoppelt zu halten.
Sie können die NullRefChecker -Klasse des Projekts verwenden, um eine höfliche Warnung auszugeben, wenn erforderliche Referenzen im Inspector fehlen. Rufen Sie einfach irgendwo (z. B. in Awake) die statische Validate- Methode auf, nachdem jede Komponente eingerichtet oder initialisiert wurde.
Fügen Sie das benutzerdefinierte optionale Attribut hinzu, um die Prüfung zu ignorieren, ob das Feld nicht festgelegt werden kann.
Ereignisse verwenden
Wie also bringen Sie diese unterschiedlichen Systeme in Ihrer Anwendung dazu, zusammenzuarbeiten?
Eine Lösung besteht darin, ein Ereignis zum Senden von Nachrichten zwischen Objekten zu verwenden. Die Ereignisse folgen dem Sender-Zuhörer-Modell, das in der Abbildung oben visualisiert ist.
Hier abonniert das hörende Objekt das Ereignis beim Sender, anstatt eine Methode aufzurufen oder direkt auf eine Eigenschaft zu verweisen.
Änderungen an einer Komponente wirken sich weniger stark auf die anderen aus. Beim Ändern des Codes können immer noch Dinge kaputt gehen, aber die Objekte sind bei weitem nicht mehr so stark miteinander verflochten. Das Ereignis in der Mitte fungiert als Puffer zwischen ihnen.
Wir beschreiben Objekte in dieser Sender-Hörer-Beziehung oft als lose gekoppelt.
Weitere Informationen zu Ereignissen und dem Beobachtermuster finden Sie in unserem technischen E-Book „ Verbessern Sie Ihren Code mit Spielprogrammiermustern“.

EIN ZENTRALISIERTES EVENTSYSTEM
Zentralisierte Ereignisse
Im oben beschriebenen Szenario ist der Sender nur für die Aussendung eines Signals verantwortlich. Es ist egal, welche Objekte zuhören.
Der Listener muss jedoch noch über gewisse Kenntnisse über den Sender verfügen, um den Delegaten mithilfe der Methoden OnEnable und OnDisable abonnieren und abbestellen zu können.
Sie können den Sender und den Listener weiter entkoppeln, indem Sie Ereignisse in eine statische Klasse verschieben. Eine allgemeine Klasse „Spielereignisse“ kann dabei helfen, eine zusätzliche Abstraktionsebene zwischen den beiden einzufügen. Dadurch kann eine Verbindung zwischen Sender und Hörer hergestellt werden, ohne dass diese direkt voneinander Kenntnis haben.
In diesem Beispiel verwenden wir der Einfachheit halber eine statische GameEvents- Klasse. In einem realen Produktionsszenario ist es jedoch besser, es nach Funktion in kleinere, spezialisierte Klassen aufzuteilen, wie etwa UIEvents, GameStateEvents, HealthEvents, InventoryEvents usw.
Sie können beispielsweise statische Ereignisse zum Beenden der Anwendung, zum Anzeigen eines UI-Bildschirms oder zum Laden einer Szene erstellen. Indem Sie diese Ereignisse statisch machen, können Sie von jedem Teil Ihrer Anwendung aus auf sie zugreifen.
Sie können beispielsweise GameEvents wie im folgenden Beispiel erstellen.
Das statische GameEvent fungiert als Vermittler zwischen dem ursprünglichen Sender und dem Zuhörer. Bei Änderungen beim Empfänger oder Absender ist die Wahrscheinlichkeit geringer, dass sie sich auch auf den jeweils anderen auswirken.
Folglich treten beim Aktualisieren des Codes weniger unerwartete Nebenwirkungen auf. Durch die Speicherung Ihrer Ereignisdefinitionen an einem einzigen Ort lassen sie sich außerdem leichter verwalten.
Obwohl statische GameEvents effektiv sind, sind sie für Ihre Spieleentwickler möglicherweise nicht sehr zugänglich. Da sie statisch sind, müssen sie im Code definiert werden und sind im Editor nicht nativ serialisierbar.
Erwägen Sie für ein editorfreundlicheres System die Implementierung von Ereignissen basierend auf ScriptableObjects.
using UnityEngine;
using System;
public static class GameEvents
{
public static Action ExitApplication;
public static Action HomeScreenShown;
public static Action<float> LoadProgressUpdated;
}
EREIGNISKANÄLE WEITERLEITEN SIGNALE ZWISCHEN SENDER UND ZUHÖRERN.
Konfigurieren von Ereigniskanälen
Auf ScriptableObjects basierende Ereignisse bieten eine grafische Alternative zu statischen Ereignissen. Obwohl beide ähnliche Funktionen erfüllen, sind ScriptableObjects tendenziell designerfreundlich, da sie im Inspector angezeigt werden.
Da sie ein Signal von einem Sender an einen Zuhörer weiterleiten, kann man sie sich als „Ereigniskanäle“ vorstellen, die einer Übertragung von einem Funkturm entsprechen.
Jedes ScriptableObject mit Folgendem kann als Ereigniskanal fungieren:
- Ein Delegat (wie UnityAction oder System.Action): Dadurch werden Abonnenten benachrichtigt und Daten als Parameter übergeben.
- Eine Methode zum Auslösen von Ereignissen: Diese öffentliche Methode ruft den Delegierten auf.
Sie können beliebig viele Ereigniskanäle einrichten, um verschiedene Aspekte des Gameplays zu bestimmen.
UnityAction und System.Action sind beide Delegierte. Sie können einen oder beide Typen in Ihrem Projekt verwenden.
UnityAction schafft ein künstlerfreundlicheres Erlebnis. Andernfalls verwenden Sie den System.Action-Delegierten.
Nachfolgend finden Sie ein Beispiel für einen VoidEventChannelSO aus dem Projekt. Dies ist ein ScriptableObject-basiertes Ereignis, das keine Parameter übergibt.
Hier verwenden wir eine UnityAction namens OnEventRaised und stellen eine öffentliche RaiseEvent-Methode bereit.
using UnityEngine;
using UnityEngine.Events;
[CreateAssetMenu(menuName = "Events/Void Event Channel",
fileName = "VoidEventChannel")]
public class VoidEventChannelSO : DescriptionSO
{
[Tooltip("The action to perform")]
public UnityAction OnEventRaised;
public void RaiseEvent()
{
if (OnEventRaised != null)
OnEventRaised.Invoke();
}
}

ERSTELLEN SIE EREIGNISKANÄLE IM PROJEKT.
Erstellen der Ereigniskanalressourcen
Erstellen Sie das Ereigniskanal-Asset im Projekt, um es zu verwenden. Sie können das Menü „Erstellen“ verwenden oder ein vorhandenes Asset duplizieren.
Benennen Sie jedes Asset um und verwenden Sie das Beschreibungsfeld, um jedes ScriptableObject-Asset zu identifizieren. Denken Sie daran, dass jeder Ereigniskanal als Asset auf Projektebene existiert. Sie werden in Ihren MonoBehaviours auf diese Assets verweisen.
Obwohl es optional ist, können Sie die auf ScriptableObjects basierenden Ereigniskanäle mit dem Suffix _SO kennzeichnen, um sie von anderen ScriptableObjects zu unterscheiden, die Daten übertragen (die das Suffix _Data haben).
Ordner und Namenskonventionen können Ihnen dabei helfen, die Organisation Ihres Projekts aufrechtzuerhalten. Sie möchten diese an die Anforderungen Ihres Projekts anpassen. Weitere Informationen finden Sie unter „Erstellen eines C#-Styleguides“ .

WEISEN SIE DEN EREIGNISKANAL IM INSPEKTOR ZU.
Auslösen von Ereignissen
Jedes Objekt in Ihrer Szene kann jetzt auf den Ereigniskanal verweisen und das Ereignis mit der Methode RaiseEvent aufrufen. Sehen Sie sich beispielsweise unten das Beispiel für MonoBehaviour mit einer TriggerEvent- Methode an.
Im Inspector muss das ScriptableObject-Asset dem Feld m_EventChannel zugewiesen werden. Wenn etwas TriggerEventaufruft, wird das Ereignis ausgeführt. Alles, was zuhört, erhält dann eine Benachrichtigung.
Dieser Mechanismus verleiht Ihrer Spieleanwendung ein hohes Maß an Interaktivität. Jedes Modul oder System löst ein Ereignis aus (z. B. registriert das Eingabesystem einen Tastendruck, ein Ball kollidiert mit einer Wand usw.). Als Antwort darauf reagiert etwas anderes.
public class EventRaiser: MonoBehaviour
{
[SerializeField]
private VoidEventChannelSO m_EventChannel;
public void TriggerEvent()
{
m_EventChannel.RaiseEvent();
}
}

DER SPIELLEITER HÖRT BESTIMMTE EREIGNISKANÄLE AB UND ÜBERTRAGT SIE AUF ANDEREN.
Auf Ereignisse warten
Um einen Listener einzurichten, muss ein MonoBehaviour oder eine andere Komponente das OnEventRaised -Ereignis des Ereigniskanals abonnieren. Normalerweise geschieht dies inOnEnable, wie im folgenden Beispiel.
Wenn der Ereigniskanal ein Ereignis auslöst, wird als Reaktion darauf die Methode HandleEvent ausgeführt. Dieser Mechanismus kann je nach Kontext des Ereignisses für verschiedene Zwecke verwendet werden, beispielsweise zum Abspielen von Sounds oder Effekten, zum Ändern von Einstellungen usw.
So haben wir im PaddleBallSO- Projekt die Hauptspielschleife eingerichtet. Der GameManager hört einen Satz Ereigniskanäle ab und sendet dann auf einem anderen. Dadurch können verschiedene Systeme Nachrichten untereinander senden, ohne dass notwendigerweise direkte Abhängigkeiten bestehen.
Melden Sie sich abschließend vom Ereignis OnEventRaised in der Methode OnDisable ab, um Fehler oder Speicherlecks zu vermeiden.
public class EventListener: MonoBehaviour
{
[SerializeField]
private VoidEventChannelSO m_EventChannel;
private void OnEnable()
{
m_EventChannel.OnEventRaised += HandleEvent;
}
private void OnDisable()
{
m_EventChannel.OnEventRaised -= HandleEvent;
}
private void HandleEvent()
{
Debug.Log("Event received");
}
}

CODEFREIE INTERAKTIVITÄT IM INSPECTOR EINGERICHTET
Hinzufügen eines Codeless-Listeners
Wenn Sie mit Designern zusammenarbeiten, möchten Sie ihnen möglicherweise ein vorkonfiguriertes Allzweckskript zur Verfügung stellen, das auf ein Ereignis achten kann. Dadurch können sie Spielinteraktionen ohne Programmierer erstellen.
Der VoidEventChannelListener ist ein Beispiel hierfür. Diese Komponente löst ein UnityEvent aus, wenn sie ein Signal von einem Ereigniskanal empfängt. Fügen Sie einfach den VoidEventChannelListener zu einem GameObject hinzu und legen Sie dann den Ereigniskanal und die UnityEvent-Logik fest.
Ein Designer kann dann mit nur wenigen Einstellungen im Inspector einen Prototyp einer ereignisgesteuerten Logik erstellen.
Beispielsweise lauscht das GameOverSounds- Prefab auf den GameOver_SO- Ereigniskanal. Sobald dieses Ereignis empfangen wird, gibt es über das UnityEvent m_Response einen Ton auf der angegebenen Audioquelle wieder.
Die Klasse VoidEventChannelListener enthält auch eine nützliche Verzögerung, um das Timing für jede Antwort anzupassen.
Mit ein wenig Übung ist dies eine einfache Möglichkeit, Interaktionen zwischen Ihren verschiedenen Systemen und Modulen aufzubauen.

ZUM SENDEN UND EMPFANGEN MARKIERTE EREIGNISKANÄLE
So helfen Ereigniskanäle
Da sie auf Projektebene existieren, sind Ereigniskanäle global zugänglich. Dadurch können sie jedes Objekt in der Szenenhierarchie verbinden und die Verbindung auch beim Laden der Szene aufrechterhalten.
Jedes Objekt kann als Sender oder Zuhörer fungieren. Die Frage ist lediglich, wie es mit dem Ereigniskanal interagiert. Dies gibt Ihnen viel Flexibilität beim Senden von Nachrichten.
Notiz: Es empfiehlt sich, im Inspektor anzugeben, ob der Kanal zum Senden oder Empfangen dient. Verwenden Sie hierzu das HeaderAttribute .
Ein Nebeneffekt der Verwendung von Ereignissen auf Projektebene besteht darin, dass sie häufig die Notwendigkeit eines Singletons ersetzen können. Ereigniskanäle sind weltweit verfügbar und können daher alles mit allem verbinden. Lassen Sie sie In-Game-Systeme wie Kameras, Quests, Gesundheit und Erfolge steuern – und das alles, ohne unnötige Abhängigkeiten zu schaffen.
Da eine ereignisbasierte Architektur nur bei Bedarf ausgeführt wird, ist sie zudem optimierter als die Aktualisierungsmethoden von MonoBehaviour.
Die Funktionssignatur eines Basisereignisses
Diese VoidEventChannelSO-Klasse funktioniert nur für Ereignisse, die keine Parameter benötigen. Oftmals benötigt das ausgelöste Ereignis zusätzliche Datennutzlasten, um aussagekräftig zu sein.
Wenn Sie beispielsweise ein Ereignis senden, das einem Gesundheitssystem Schaden zufügt, möchten Sie möglicherweise einen Wert für das Ziel übergeben, die zu sendende Schadensmenge, die Art des Schadens usw.
Sie können die Funktionssignatur Ihres Basisereignisses ändern, um den Ereigniskanal dafür besser geeignet zu machen. Das Projekt definiert zu diesem Zweck einen GenericEventChannelSO. Schauen Sie sich das folgende Beispiel an.
Dies ist eine abstrakte Klasse mit einem einzelnen generischen Parameter. Daraus leiten Sie weitere Ereigniskanäle ab. Diese können dann einen einzelnen Parameter übergeben, beispielsweise einen Float, Int oder Bool.
Wie VoidEventChannelSO verfügt GenericEventChannelSO über eine UnityAction namens OnEventRaised. Dieses Mal überträgt die Aktion jedoch einen Parameter vom Typ T.
Externe Objekte rufen die entsprechende öffentliche RaiseEvent-Methode auf. Wenn das Ereignis über Listener verfügt, wird es beim Übergeben eines bestimmten Parameters ausgeführt.
public abstract class GenericEventChannelSO<T>: DescriptionSO
{
public UnityAction<T> OnEventRaised;
public void RaiseEvent(T parameter)
{
if (OnEventRaised == null)
return;
OnEventRaised.Invoke(parameter);
}
}
Konkrete Eventkanäle schaffen
Nun müssen Sie nur noch konkrete Ereigniskanäle aus GenericEventChannelSO ableiten und den Wert für T eintragen.
Abgesehen vom üblichen CreateAssetMenu-Attribut sind keine expliziten Implementierungsdetails erforderlich.
Das Erstellen eines Ereigniskanals, der einen Float überträgt, FloatEventChannelSO, ist unkompliziert. Schauen Sie sich das Codebeispiel unten an.
So einfach ist das! Verwenden Sie diesen Workflow, um zusätzliche für BoolEventChannelSO, IntEventChannelSO usw. zu erstellen.
Wenn Sie mehr als einen Parameter als Nutzlast benötigen, definieren Sie nach Bedarf zusätzliche generische Klassen (z. B. GenericEventChannelSO<T,U>, GenericEventChannelSO<T,U,V> usw.).
[CreateAssetMenu(menuName = "Events/Float EventChannel", fileName = "FloatEventChannel")]
public class FloatEventChannelSO : GenericEventChannelSO<float> {}

ABLAUF DER EREIGNISSE, WENN DER BALL EIN TOR TRIFFT
Alles zusammenfügen
Die Idee besteht darin, die Anwendung in kleinere, modularere Teile zu zerlegen. Durch die Festlegung klarer Grenzen wird verhindert, dass sich diese Teile durch Abhängigkeiten miteinander verflechten, und Spaghetticode wird vermieden.
Komponenten, die keine direkte Kenntnis von externen Objekten haben, können nichts manipulieren, was sie nicht manipulieren sollen. Stattdessen sind sie gezwungen, Nachrichten über Ereigniskanäle zu senden und zu empfangen.
Wie das funktioniert, können Sie sehen, wenn Sie eine kleine Sequenz des Paddle-Ball-Spielverlaufs verfolgen. Stellen wir uns beispielsweise vor, was passiert, wenn ein Ball mit einem ScoreGoal kollidiert:
Die Komponente ScoreGoal registriert eine Kollision. Nachdem der Ball erkannt wurde, wird ein Ereignis im Ereigniskanal GoalHit_SO ausgelöst. Dadurch wird die Spieler-ID des punktenden Spielers weitergegeben.
Der Ereigniskanal benachrichtigt den GameManager, der als Reaktion darauf einen weiteren Ereigniskanal namens PointsScored_SOauslöst. Dadurch wird auch die Spieler-ID weitergegeben.
Dieser Kanal benachrichtigt den ScoreManager, der den Punktestand (in einem separaten Objekt gespeichert) erhöht und die UI-Komponenten aktualisiert. Anschließend werden die Punktestände beider Spieler über den Ereigniskanal ScoreManagerUpdated_SO weitergegeben.
Als Antwort darauf prüft das Ziel ScoreObjective_SO , ob ein Spieler die Zielpunktzahl erreicht hat.
Wenn eine Gewinnbedingung erreicht ist, endet das Spiel. Andernfalls setzt der GameManager die Runde zurück und der Ball kommt wieder ins Spiel.
Auf den ersten Blick mag es wie viel Mehrarbeit erscheinen, einen Score-Wert um einen Punkt zu erhöhen. Die Absicht besteht jedoch darin, alle beteiligten Teile zu isolieren: Der Ball, der ScoreManager, der GameManager, der ObjectiveManager usw.
Jeder Teil der Anwendung verfügt über eine gewisse Autonomie, wodurch jeder einzelne Teil leichter zu testen ist. Das Hinzufügen neuer Systeme muss die vorhandene Logik nicht unterbrechen. Tatsächlich kann es sein, dass ihnen das ursprüngliche Gameplay überhaupt nicht auffällt.
Stellen Sie sich vor, Sie möchten den Vertonungsprozess durch sekundäre Effekte wie Töne und Animationen begleiten. Sie könnten neue Komponenten erstellen, die auf die richtigen Ereignisse hören und entsprechend reagieren. Die zugrunde liegende Logik und der Spielfluss können unverändert bleiben, auch wenn Sie die neuen Systeme hinzufügen.
Denken Sie daran, dass das Mantra der SOLID-Programmierung lautet: „Offen für Erweiterungen, geschlossen für Änderungen.“ Sie möchten Ihrer Software neue Funktionen hinzufügen können, ohne den vorhandenen Code ändern zu müssen. Die Verwendung solcher Ereigniskanäle ermöglicht Skalierbarkeit.

EDITOR-SCRIPTING KANN BEI DER DEBUGGERÄTE-SUCHE HELFEN.
Debuggen von Ereignissen
Die ereignisgesteuerte Architektur erleichtert die Fehlerbehebung und Wartung. Kleinere Teile lassen sich leichter testen, egal ob Sie automatisierte Unit-Tests mit dem Unity Test Framework schreiben oder nur informell Fehler beheben. Dadurch können Sie sich auf ein bestimmtes Problem konzentrieren und isoliert testen.
Benutzerdefinierte Editor-Skripte können hier hilfreich sein. PaddleBallSO führt einige Tools vor, mit denen Sie den Ablauf Ihrer Anwendung bei der Verwendung von Ereigniskanälen verfolgen können:
- Die meisten Ereigniskanäle im PaddleBallSO- Projekt zeigen im Inspector eine Liste von Listenern an. Klicken Sie auf den Namen jedes Zuhörers, um ihn in der Hierarchie hervorzuheben.
- Eine benutzerdefinierte RaiseEvent- Schaltfläche kann nach Belieben ein Scheinereignis aufrufen (unter Verwendung des Standardwerts T, wenn eine Nutzlast übertragen wird). Während die Anwendung läuft, können Sie sie einfach manuell mit einem einzigen Klick auslösen.
Wählen Sie zur Fehlerbehebung bei Ereigniskanälen das Asset ScriptableObject aus. Testen Sie das Ereignis bei Bedarf manuell. Der Inspector kann Sie durch die Objekte führen, die möglicherweise zuhören. Wählen Sie die Listener aus, die Sie genauer untersuchen möchten.
Wenn Sie die Ereigniskanäle mit dem HeaderAttritute gekennzeichnet haben, können Sie mehrere Ereignisse zurückverfolgen, um den Logikfluss zu verstehen.

Weitere ScriptableObject-Ressourcen
Wir hoffen, dass Ereigniskanäle und ereignisgesteuerte Architektur Ihren neuen und zukünftigen Projekten von Nutzen sein können.
Lesen Sie mehr über Entwurfsmuster mit ScriptableObjects in unserem technischen E-Book „ Erstellen Sie modulare Spielearchitektur in Unity mit ScriptableObjects“. Weitere Informationen zu allgemeinen Entwurfsmustern für die Unity-Entwicklung finden Sie unter „ Verbessern Sie Ihren Code mit Spielprogrammiermustern“.