Jump to content
Unity Insider Forum

System Architektur frage :thinking_face:


Cxyda83

Recommended Posts

Moin zusammen!

ich arbeite zur zeit an einem recht aufwändigen WiSim game und habe bereits eine recht saubere Architektur implementiert. Im prinzip geht es in die MicroServices Architektur in der sich jeder Service im genau 1 Feature oder 1 "Problem" innerhalb meines games kümmert (Siehe Architektur Diagramm unten). Ich habe also

  • View Layer der Daten mithilfe des DataProviders (readOnly) abfragen und Commands über den MessageHub publishen
  • Services subscriben auf die Commands, führen dann Logik aus und publishen dann Events
  • Jedes Model verwealtet alle DatenObjekte genau eines typs, führt logik aus und schreibt die Daten zurück.

In der aktuellen Implementieren publishen Models auch Events je nach dem ob sie (nach meiner ansicht) atomare Änderungen vornehmen von denen jeder wissen solle wie z.B. das hinzufügen / entfernen / ändern von Items im Inventar.

Jetzt bekomme ich jedoch langsam das Problem das wenn ein Service eine komplexere Operation ausführt, mehrere Events hintereinander gepublished werden und meine Views durcheinander bringt... ein Beispiel:

Der Trading Service kümmert sich darum das Items von NPCs gekauft und verkauft werden können. Für diese Aufgabe braucht er folgende Systeme:

  • Market (read/write), um die aktuellen Preise der Items zu ermitteln und anschließend neue Marktpreise zu berechnen
  • Reputation (read/write), um das Ansehen des jeweiligen Characters herauszubekommen, was dann einfluss auf den Preis hat
  • Inventory (read/write), für menge / verfügbarkeit der Items und änderungen bei erfolgreichem handel
  • ...

Da das Trading System bei erfolgreichem / gescheitertem Handel Änderungen in einigen anderen Systeme vornimmt ist nun meine Frage ob

option 1) : das Trading Model mit den anderen System Models arbeitet um so direkt read / write operationen durchzuführen

option 2) : das TradingModel ausschließlich mit anderen Services kommuniziert um schreib operationen durchzuführen und ausschließlich mit dem DataProvider kommuniziert um Daten anderer Systeme zu lesen

option 3 ) weitere vorschläge ?

Beide optionen haben Vor- und Nachteile vorallem wenn man darüber nachdenkt wer (services oder models) Events nach durchführung einer operation published.

Bei option 2 würden eine ganze menge events gepublished werden z.B.

  • InventoryChangedEvent (NPC Inventory)
  • InventoryChangedEvent (Player Inventory)
  • ReputationChangedEvent (NPC)
  • MoneyChanged (Player Money)
  • MoneyChanged (NPC Money)
  • TradeSuccessfulEvent

Würden die Models untereinander alle nötigen Operationen ausführen könnte am ende nur 1 event gepublished werden (TradeSuccessfulEvent) aber hier besteht das große Risiko das irgendwelche Views / Systeme änderungen nicht mitbekommt da sie nicht einfach nur auf 1 event hören müssen sondern auf ALLE events von Systemen die ein SubSystem ändern.

Aus diesem Grund hätte ich gerne einmal eure Meinung dazu gehört 🙂 Im moment sind bei mir beide optionen am Start aber ich bin jedes mal hin und her gerissen welchen weg ich gehen soll und das würde ich gerne abstellen.

 

Besten dank schon mal im vorraus!

 

untitled(1).jpg

Link zu diesem Kommentar
Auf anderen Seiten teilen

Hmm.... niemand ? ^^ Hat keiner eine Meinung dazu ?

Liegt das daran das ich völlig auf dem Holzweg bin oder das Problem völlig over-engineered habe ? 🤔 Ich gebe zu das ist nicht die typische Frage die man hier so findet^^ aber vielleicht will sich ja doch jemand äußern 🙂

 

 

Link zu diesem Kommentar
Auf anderen Seiten teilen

Eine Meinung dazu habe ich schon, aber was soll ich sagen.... Ich hatte selber schon mal eine Art Wirtschaftssimulation begonnen und gemerkt dass es gar nicht soo leicht ist, die ganzen Dinge miteinander zu verknüpfen.
Auch ich hatte da mit Events gearbeitet und sie für schlecht befunden! :D

Also an sich ist das mit den Events schon klasse, wenn andere Systeme einfach nur drauf hören sollen. Sobald es aber (wie bei dir) hin und her geht, der Sender also auch ein Empfänger sein kann, wird es kompliziert.

Ich denke, dass es nicht so viel Sinn macht alles in klitzekleine Module aufzuspalten, die dann alle miteinander kommunizieren müssen.
Das hier würde ich anders machen:

Zitat
  • Market (read/write), um die aktuellen Preise der Items zu ermitteln und anschließend neue Marktpreise zu berechnen
  • Reputation (read/write), um das Ansehen des jeweiligen Characters herauszubekommen, was dann einfluss auf den Preis hat
  • Inventory (read/write), für menge / verfügbarkeit der Items und änderungen bei erfolgreichem handel

Der Market muss nicht beschrieben werden. Er ermittelt einfach, anhand der Anzahl der verfügbaren Dinge, einen Preis. Dieser Preis ändert sich nicht sofort bei jeder Transaktion, sondern erst nachdem der Besuch im Markt beendet wurde (oder nach einer gewissen Zeit danach). Also erst danach gibt es ein Event, damit der Market neue Preise generieren kann. Klar, wenn irgendwie neue Ware von woanders her rein kommt, kriegt er auch ein Event.

Die Reputation ist eine Eigenschaft des Players, die sich ja beim Handeln normalerweise nicht verändert. Also muss sie bei Handelsbeginn einmalig abgefragt werden und als Berechnungsgrundlage für die Marktpreise einfließen.

Inventory ist natürlich auf beiden Seiten wichtig. Der Mart hat eins und der Player auch. Bei jedem Kauf bzw. Verkauf ändern sich sofort auf beiden Seiten die Werte. Das Inventory des Players informiert also das Inventory des Marktes und umgekehrt.

Nach verlassen des Shops werden die neuen Daten abgelegt und der Market bekommt ein Event, dass er die Preise neu berechnen kann. Jetzt "könnte" auch ein Event dafür sorgen, dass die Reputation sich verändert.

Also:

Market (readOnly) berechnet nur Preise anhand der Verfügbarkeit und der Reputation. Immer wenn sich das Warenlager verändert (oder zyklisch nach gewisser Zeit), entsteht ein Event, welches zur Neuberechnung der Grundpreise führt. Dieser Grundpreis wird über die Reputation des Players verändert. Markt schaut also in sein Lager und begutachtet sich den Player. ;)
Das macht er aber nur, wenn der Markt betreten wird.

Reputation (read/write) wird vom Market ausgelesen und von anderen Dingen beschrieben. Wobei meiner Meinung nach der Handel nicht dazu gehört. Aber selbst wenn, dann erst nachdem der Markt verlassen wurde.

Inventory (read/write) Liest zu Beginn die Daten aus dem Datenmodul aus. Es wird sofort nach jeder Transaktion verändert. Zum Inventory gehört wahrscheinlich auch das Geld. Ist also eine Ware nicht mehr verfügbar oder reicht das Geld für die gewünschte Transaktion nicht mehr aus, kann nicht gehandelt werden. Ob du jetzt auch noch irgendwelche Dialoge mit dem Händler führst, die einen Handel auch unterbinden könnten, weiss ich ja nicht. Ich gehe mal davon aus, dass das mit gescheitertem Hnadel meinst.
Nach verlassen des Marktes werden die neuen Inventory-Daten dem Datenmodul übergeben.


Fazit:
Hier würde jetzt der Market nur aktiv werden, wenn der Player den Shop betritt. Er bekommt ein Event zur Neuberechnung und diese berechneten Werte können dann angezeigt und genutzt werden. Markt gehört dann wohl in den View Layer (auch wenn er rechnet).
Die Reputation wird nur ausgelesen. Könnte aber nach verlassen des Shops ein Event bekommen um sich zu verändern.
Das Inventory füllt sich beim betreten des Shops mit Daten. Jeder Handel, verändert diese Daten. Beim verlassen des Shops, wird das Datenmodul mit den veränderten Daten beschrieben.

Viele Events würde es also nicht geben. Jedenfalls würden sich die Events nicht gegenseitig behindern.
Wie du das jetzt in dein Blockschaltbild einbaust, musst du selber raus finden. :D

Link zu diesem Kommentar
Auf anderen Seiten teilen

Hey Malzbie! Erstmal danke für deine (ausführliche) Antwort und deinen input !  :D

Ja das Pub/Sub pattern (Publisher / Subscriber)macht dinge (erstmal) nicht einfacher zahlt sich aber vorallem in größeren Projekten auf jedenfall aus. Das ist aber auch nicht das Problem das läuft :)

Zum Markt:
Da der markt nicht nur vom Spieler besucht werden kann sondern auch von anderen NPCs die den Preis beeinflussen, ändern sich die Preise auch während des Markt besuchs. Außerdem ist es bei WiSims wie z.B. DIe Patrizier / Port Royale üblich das sich auch die Preise am markt ändern während der spieler Kauft z.B. wenn der Spieler 100 einheiten kauft und nach 50 würde ein gewisses Limit überschrtten werden, sodass nicht alle 100 einheiten gleich viel kosten. Aus diesem Grund kauft und verkauft die Logik am markt immer nur 1 Einheit (und das dann z.b. 100 mal) um jedes mal den marktpreis neu zu ermitteln und anzupassen.... Ja ich weis kompliziert aber ich schätze so läuft das auch bei anderen WiSims ¯\_(ツ)_/¯

Reputation:
Die reputation ändert sich auch während der Spieler Handelt nämlich wenn er dem NPC ein schlechtes angebot unterbreitet, das dann abgelehnt wird, und die reputation geht in den keller. Bei guten / erfolgreichen angeboten steigt sie. Du hast recht das die reputation dann am Spieler hängt (oder hängen sollte) aber ich hätte eigentlich auch gerne das NPCs untereinander eine reputation (Ansehen) haben die dann die Preise und ihr handeln entsprechend beeinflussen.

Inventory:
Auch hier schreibe ich während des Handels die änderungen. Andernfalls würde ich probleme bekommen wenn es z.B. nur 100 Wolle am markt gibt und ein anderer NPC / Spieler kauft 50 Wolle Währen der Spieler gerade z.B. 100 wolle kauft möchte.

Ich werde nochmal gründlich über deine Anmerkungen nachdenken aber ich denke in dem von mir visionierten Spiel mit NPCs (Bots) und eventuell multiplayer komme um eine Architektur dieser art nicht herum.

Ich schätze auch eher das meine Views das problem sind das manchmal probleme mit den events bekommen, da sie ab und zu mehr UIs updaten und nicht nur die UI elemente die sie selbst verwalten

 

P.S. Link zum aktuellen Trading Prototypen um selbst mal zu testen und besser einzuschätzen um was es grade geht :)

Viel Spaß
http://polybeast.de/UnityProjects/MVPs/MedievalLife/Trade/index.html

Link zu diesem Kommentar
Auf anderen Seiten teilen

Ja, das ist natürlich eine ganz andere Hausnummer!
Jetzt verstehe ich, was du da so machst. Trotzdem ist es nicht realistisch, dass sich der Preis eines Produktes wärend deines Marktbesuchs ändert. Schon gar nicht im Mittelalter! Wir sind ja schließlich nicht ander Börse mit Computerhandel. ;)
Aber selbst wenn sich der Preis ändern sollte, so kann es erst nach einem Handel sein. Also der Preis, den du vor einen Kauf siehst, bleibt solange bestehen, bis du eine gewisse Menge gekauft hast. Nach dem Handel, egal ob erfolgreich oder nicht, könnte er neu berechnet werden.
Genauso darf es nicht sein, dass in dem Markt, wo du gerade bist, ein NPC wärend deines Handels den Preis oder die Verfügbarkeit des Produktes ändern kann. Du bis schließlich an der Reihe und nicht der NPC.

Somit gibt es immer nur Änderungen nach einem Handel. Das betrifft die Reputation, den Preis und die Verfügbarkeit. Dass sich das Inventory des Players zur selben Zeit ändern kann, ist eh klar.
NPC's sollten, meiner Meinung nach, wärend eines Handels in diesem Shop keinen Einfluss haben.

Also:
Sobald du dem Markt besuchst, setzen die NPC's erst einmal aus. Du siehst die Güter und deren Preise. Jetzt kannst du Güter in gewünschter Anzahl in deinen Warenkorb legen und versuchen einen guten Preis auszuhandeln. Egal ob es klappt oder nicht. Nach der Aktion werden die Shopdaten aktualisiert. Das bedeutet, jetzt könnten auch einmal alle NPC einen Handel ausführen. Also alle NPC, die auch am Tresen stehen und gewartet haben, handeln jetzt nacheinander (das alles passiert natürlich in einem Frame). Danach bist du wieder an der Reihe.
Du siehst jetzt dadurch evtl. andere Güter und/oder andere Preise, weil sich das Lager verändert hat. Jetzt könntest du wieder handeln.
Verlässt du den Shop, können die NPC machen was sie wollen.

Es gibt also ein Event vor jedem Handel, welches den Shop aktualisiert indem er seine Datenbanken abfragt und dir die Veränderung anzeigt.
Nach einem Handel gibt es 2 weitere Events. Eines für die Inventorys und eines für die Reputation.

Und so müsste es dann auch für jeden NPC sein. (1) Shop wird aktualisiert, Handel wird getätigt, (2)Inventorys werden verändert und (3)Reputationen werden angepasst.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Hallo

 

Ich stelle mal eine generelle Frage: Diese UNL-Diagramm, die du verlinkt hast, entstehen die vor, während oder nach der Arbeit mit Unity. Ich frage, weil ich das total beeindruckend finde, schon vorher abzusehen, was da alles auf einen zukommt. Ist das eine Frage der Erfahrung? Schränkt ihr euch ein, um nicht immer noch mehr Features zu implementieren? Habt ihr alles vorher schon im Kopf bzw. auf Papier? Ich merke, dass ich manchmal versuche, Projekte zu überschauen und spätestens nach zwei Stunden Arbeit im Editor ist alles wieder anders. Geht das nur mir so?

 

Christoph

Link zu diesem Kommentar
Auf anderen Seiten teilen

Moin Chrische!

hmm also deine frage ist ziemlich vielschichtig ich versuch mal was dazu zu sagen ^^

Idealerweise entstehen so architektur diagramme bevor man anfängt zu coden da man (mit der nötigen erfahrung) schnell offensichtliche fehler in der kommunikation oder fragwürdige abhängigkeiten erkennen kann. In Größeren Teams ist das auch wichtig und sinnvoll da man sich dann auf den schwierigsten teil, die Planung, konzentrieren kann. Hat man diesen teil gut und gewissenhaft abgeschlossen fehlt nur noch das "herunter" programmieren. Da dann alle teammitglieder eine gute vorstellung von dem Problem und der Lösung haben kann man auch ohne probleme die Aufgabe an mehrere programmierer verteilen.

In meinem fall ist das diagramm aber während oder nach der arbeit in Unity entstanden. Ich hatte die Idee von der architektur schon vorher und habe die dann umgesetzt, allerdings bin ich dann immer mal wieder leicht davon abgewichen da ich das nirgends dokumentiert hatte und ich dinge vergessen habe wenn ich mal 1 monat nicht am projekt gearbeitet hatte.

Es kann schon sein das eine Architektur entscheidung die man anfangs getroffen hat einen später einschränkt. Was sowohl gut als auch schlecht ist. Hat man neue programmierer im team hat, oder man selbst nach einigen monaten nicht mehr so genau die architektur und die abhängigkeiten im kopf hat, kann man sich nur innerhalb der vorgefertigten bahnen bewegen und kann nicht einfach wild das rad neu erfinden - das ist gut. Wenn allerdings ein neues feature implementieren soll das in der architektur noch nicht bedacht wurde und dann in der umsetzung probleme bereitet ist das natürlich schlecht. An diesem Punkt gibt es nun mehrere möglichkeiten aber im prinzig folgt die Architektur immer den Anwendungsfällen. Wenn sich also der Anwendungsfall ändert, ändert sich die Architektur.

Alles im kopf zu haben ist immer schwer, dabei helfen aber solche diagramme und natürlich erfahrung. Ging mir anfangs auch so das mein plan den ich vielleicht hatte nach wenigen Zeilen code hinfällig wurde weil ich etwas nicht bedacht hatte. Allerdings abstrahierst du mit diesen diagrammen das problem und denkst nicht darüber nach wie du eine bestimmte klasse implementierst sondern nur welceh abhängigkeiten sie hat, was ihre verantwortlichkeit ist und was sie an ausgaben zur verfügung stellt. das WIE ist hier nicht relevant

Ich hoffe ich konnte da halbwegs verständlich erklären ^^'

Link zu diesem Kommentar
Auf anderen Seiten teilen

Hallo

 

Auf jeden Fall. Wie ist das mit Features? Bist du/ seid ihr da streng und versucht euch zu beschränken oder kommt es häufig vor, dass man noch das und das implementiert. Ich hatte gerade so ein Fall, wo es immer mehr wurde und am Ende war es kein Spiel, sondern (für mich) viele Features, die aber gar nicht zum eigentlichen Ziel gepasst haben. Hat mich sehr geärgert, weil ich bei jedem einzelenen Schritt gar nicht erkannt habe, aber es dann aber jemand probierte, fragte er permanent, wozu das alles da sei....

 

Christoph

Link zu diesem Kommentar
Auf anderen Seiten teilen

🤔 hmm das hat meiner meinung nach nichts mit der architektur zutun :D

Der GameDesigner bzw der VisionKeeper sollte sich gedanken darüber machen welche features alle im spiel sein sollten und die architektur SOLLTE die implementierung dieser features ermöglichen und am besten noch stark vereinfachen (und nicht erschweren). Gibt es neue features die so vorher nicht geplant oder bedacht wurden muss sich die architektur ändern .. das passiert dann meistens nach einer Aufwandseinschätzung und dann muss überlegt werden ob das feature den aufwand wert ist, wenn ja, dann wird natürlich geändert.

Die architektur hat aber nicht die aufgabe features aus der Spielidee zu streichen oder sie nicht zuzulassen

Link zu diesem Kommentar
Auf anderen Seiten teilen

Archiviert

Dieses Thema ist jetzt archiviert und für weitere Antworten gesperrt.

×
×
  • Neu erstellen...