Verwalten des Status und der Ereignisse zwischen Komponenten in GameObject
Link zum ProjektWie jeder weiß, der mehr oder weniger mit der Unity-Plattform vertraut ist, besteht jedes
GameObject -Spielobjekt aus Komponenten (integriert oder benutzerdefiniert, was normalerweise als „Skript“ bezeichnet wird). Komponenten erben von der Basisklasse
MonoBehavior .

Und normalerweise wird gut oder oft eine direkte Verbindung hergestellt, um die Komponenten zu binden.

Das heißt, Um in einer Komponente Daten von einer anderen Komponente
abzurufen , erhalten wir diese mithilfe der
GetComponent <...> () -Methode, beispielsweise wie
folgt :

In diesem Beispiel wird ein Verweis auf eine Komponente vom Typ
SomeComponent in die Variable
someComponent eingefügt .
Bei diesem „eng gekoppelten“ Ansatz ist es insbesondere bei einer großen Anzahl von Komponenten recht leicht, verwirrt zu werden und die Integrität einer solchen Verbindung aufrechtzuerhalten. Wenn sich beispielsweise der Name einer Eigenschaft oder Methode in einer Komponente ändert, müssen Sie ihn in allen Komponenten korrigieren, die dies verwenden. Und das ist eine Blutung.
Unter dem Schnitt viele BilderErstellen einer Lösung basierend auf der „starken Verbundenheit“ von Komponenten
Wir werden ein leeres Projekt erstellen, um die übliche Situation zu reproduzieren, wenn wir bestimmte Komponenten haben und jede auf einander verweist, um Daten zu empfangen oder zu steuern.

Ich habe zwei Skripte hinzugefügt,
FirstComponent und
SecondComponent , die als Komponenten im Spielobjekt verwendet werden:

Jetzt werde ich für jede der für die Experimente benötigten Komponenten eine einfache Struktur definieren.


Stellen Sie sich nun eine Situation vor, in der wir die
Feldwerte state1 von der
FirstComponent- Komponente
abrufen und ihre
ChangeState (...) -Methode in der
SecondComponent- Komponente
aufrufen müssten . Dazu müssen Sie einen Link zur Komponente erhalten und die erforderlichen Daten in der
SecondComponent- Komponente
anfordern :

Nachdem wir das Spiel in der Konsole gestartet haben, werden wir sehen, dass wir Daten von
FisrtComponent von
SecondComponent erhalten und den Status der ersten geändert haben

Genauso können wir jetzt die Daten und in entgegengesetzter Richtung von der
FirstComponent- Komponente
abrufen, um die Daten der
SecondComponent- Komponente
abzurufen .

Nach dem Start des Spiels wird auch sichtbar, dass wir Daten empfangen und die
SecondComponent- Komponente von
FirstComponent aus
steuern können .

Dies war ein ziemlich einfaches Beispiel, und um zu verstehen, welche Art von Problem ich beschreiben möchte, wäre es notwendig, die Struktur und die Beziehungen aller Komponenten stark zu komplizieren, aber die Bedeutung ist klar. Nun ist die Verbindung zwischen den Komponenten wie folgt:


Das Erweitern eines Spielobjekts mit neuen Komponenten, wenn diese mit vorhandenen interagieren müssen, ist eher Routine. Und insbesondere, wenn sich beispielsweise der Name des
Felds state1 in der
FirstComponent- Komponente beispielsweise in
state_1 ändert und Sie den Namen ändern müssen, in dem er in allen Komponenten verwendet wird. Oder wenn die Komponente zu viele Felder hat, wird es ziemlich schwierig, sie zu navigieren.
Erstellen einer Lösung basierend auf dem „allgemeinen Status“ zwischen Komponenten
Stellen Sie sich nun vor, wir müssten nicht einen Link zu jeder interessierenden Komponente erstellen und Daten daraus abrufen, sondern es würde ein bestimmtes Objekt geben, das die Zustände und Daten aller Komponenten im Spielobjekt enthält. Im Diagramm würde es so aussehen:

Allgemeiner Status oder Allgemeines Statusobjekt (SharedState) ist auch eine Komponente, die die Rolle einer Dienstkomponente spielt und den Status aller Komponenten des Spielobjekts speichert.
Ich werde eine neue Komponente erstellen und sie SharedState nennen:

Und ich werde den Code für diese universelle Komponente bestimmen. Es speichert ein geschlossenes Wörterbuch und einen Indexer für eine bequemere Arbeit mit dem Komponentenwörterbuch, es ist auch eine Kapselung und es funktioniert nicht direkt mit dem Wörterbuch anderer Komponenten.

Jetzt muss diese Komponente auf dem Spielobjekt platziert werden, damit die anderen Komponenten darauf zugreifen können:

Als Nächstes müssen Sie einige Änderungen an den Komponenten
FirstComponent und
SecondComponent vornehmen , damit sie die
SharedState- Komponente zum Speichern ihres Status oder ihrer Daten verwenden:


Wie Sie dem Komponentencode entnehmen können, speichern wir das Feld nicht mehr, sondern verwenden den allgemeinen Status und haben über den Schlüssel "state1" oder "counter" Zugriff auf seine Daten. Jetzt sind diese Daten an keine Komponente gebunden. Wenn eine dritte Komponente angezeigt wird und auf SharedState zugreifen kann, kann er auf alle diese Daten zugreifen.
Um die Funktionsweise dieses Schemas zu demonstrieren, müssen Sie die Aktualisierungsmethoden in beiden Komponenten ändern. In
FisrtComponent :

Und in der
SecondComponent- Komponente:

Jetzt kennen die Komponenten den Ursprung dieser Werte nicht, dh bevor sie sich an eine bestimmte Komponente gewandt haben, um sie abzurufen. Jetzt werden sie einfach in einem gemeinsamen Raum gespeichert und jede Komponente hat Zugriff auf sie.
Nach dem Start des Spiels können Sie sehen, dass die Komponenten die gewünschten Werte erhalten:

Nachdem wir nun wissen, wie es funktioniert, können wir die Basisinfrastruktur für den Zugriff auf den allgemeinen Status in der Basisklasse ableiten, um nicht alles in jeder Komponente einzeln auszuführen:

Und ich werde es abstrakt machen, damit ich nicht versehentlich eine Instanz davon erstelle ... Und es ist auch ratsam, ein Attribut hinzuzufügen, das angibt, dass für diese Basiskomponente die
SharedState- Komponente erforderlich ist:

Jetzt müssen Sie die Komponenten
FirstComponent und
SecondComponent so
ändern , dass sie von
SharedStateComponent erben und alle unnötigen
Elemente entfernen:


Ok Was ist mit Methoden aufrufen? Es wird vorgeschlagen, dies auch nicht direkt, sondern über das Publisher-Subscriber-Muster zu tun. Vereinfacht.
Um dies zu implementieren, müssen Sie eine weitere allgemeine Komponente hinzufügen, ähnlich der, die die Daten enthält, mit der Ausnahme, dass diese nur Abonnements enthält und
SharedEvents heißt:

Das Prinzip ist wie folgt. Eine Komponente, die eine Methode für eine andere Komponente aufrufen möchte, führt dies nicht direkt aus, sondern durch Aufrufen eines Ereignisses, nur nach Namen, wenn Daten aus dem allgemeinen Status abgerufen werden.
Jede Komponente abonniert einige Ereignisse, die sie verfolgen kann. Und wenn er dieses Ereignis abfängt, führt er den Handler aus, der in der Komponente selbst definiert ist.
Erstellen Sie die
SharedEvents- Komponente:

Außerdem definieren wir die Struktur, die für die Verwaltung von Abonnements und Veröffentlichungen erforderlich ist.

Für den Datenaustausch zwischen Abonnements, Veröffentlichungen wird eine Basisklasse definiert, eine spezifische für den Autor jeder Veranstaltung unabhängig festgelegt und anschließend mehrere Beispiele definiert:

Jetzt müssen Sie dem Spielobjekt eine neue Komponente hinzufügen:

Erweitern Sie die
SharedStateComponent- Basisklasse ein
wenig und fügen Sie die Anforderung hinzu, dass das Objekt
SharedEvents enthält

Neben dem allgemeinen Statusobjekt muss das allgemeine Abonnementobjekt aus dem Spielobjekt abgerufen werden:


Jetzt definieren wir ein Ereignisabonnement, das wir in
FisrtComponent verarbeiten, und eine Klasse zum Übertragen von Daten über diesen Ereignistyp. Außerdem ändern
wir SecondComponent so, dass das Ereignis für dieses Abonnement veröffentlicht wird:


Jetzt haben wir jedes Ereignis namens "writedomedata" in der
FirstComponent- Komponente
abonniert und
drucken einfach
eine Nachricht an die Konsole, wenn sie auftritt. In diesem Beispiel wird die Veröffentlichung eines Ereignisses mit dem Namen "writeomedataata" in der
SecondComponent- Komponente
aufgerufen und einige Informationen übertragen, die in der Komponente verwendet werden können, die Ereignisse mit diesem Namen
abfängt .
Nachdem wir das Spiel in 5 Sekunden
gestartet haben, sehen wir das Ergebnis der Verarbeitung des Ereignisses in
FirstComponent :

Zusammenfassung
Wenn Sie nun die Komponenten dieses Spielobjekts erweitern müssen, das auch den allgemeinen Status und die allgemeinen Ereignisse verwendet, müssen Sie eine Klasse hinzufügen und einfach von
SharedStateComponent erben:
Fortsetzung des Themas