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
Fortsetzung des Themas