Jump to content
Unity Insider Forum
Sascha

Soda - ScriptableObject Dependency Architecture

Recommended Posts

Moin zusammen!

Nach etwa einem Jahr Arbeit (mit Pausen... :)) kann ich mein neues Asset Store-Paket vorstellen!

image.png

Es handelt sich dabei um eine stark weiterentwickelte Implementation der Konzepte, die in diesem Talk vorgestellt werden:

Um es kurz zu fassen: Damit könnt ihr extrem saubere Architekturen bauen, doch der Kniff ist: Ihr arbeitet hier mit Unity und nicht dagegen an.

Das Paket ersetzt keine von Unitys Funktionalitäten, es gibt kein "das kannst du jetzt so nicht mehr benutzen". Es wird ausschließlich erweitert, was schon da ist. Ich sag mal so... ich arbeite nicht mehr ohne, seit ich das Ding für meine eigenen Projekte gebaut habe.

Falls ihr euch jetzt fragt, wie das geht... ich könnte erstmal eine Menge schreiben, aber schaut euch besser den Talk an, der ist hervorragend.

Hier geht's zum Paket: https://assetstore.unity.com/packages/tools/integration/soda-scriptableobject-dependency-architecture-137653

Bei Fragen gerne fragen!

  • Like 3

Share this post


Link to post
Share on other sites

Wow, ein wirklich nutzliches Asset hast du entwickelt. Vor allem, dass man Events als Scriptable Objects erstellen kann. Hatte schon viel Stress gehabt mit ganzen Objekt Verbindungen, so dass ich mit der Zeit einfach die Übersicht verlor :D Ich denke mit dem Asset würde mir das nicht passieren. Ich habe bei mir auch einiges nach Ereignise umgebaut. allerdings wäre es natürlich schöner, wenn man nach Ereignis Scriptable klickt und sofort sieht, was ausgelöst wird. 

Ich frage mich aber wie es performancemäßig aussieht. Wann sollte man mit Ereignis auflösen und wann einfache Objektverbinding ausreichen würde. Und zu dem Asset frage ich mich ob man mit dem einen Ereignis weitere Ereignise auslösen kann?

Share this post


Link to post
Share on other sites

Danke schonmal für's Feedback!

vor 9 Stunden schrieb TheOnlyOne:

Ich frage mich aber wie es performancemäßig aussieht. Wann sollte man mit Ereignis auflösen und wann einfache Objektverbinding ausreichen würde.

Performance kosten die Dinger nichts besonderes. Es geht deshalb bei dieser Entscheidung viel mehr um saubere Architektur. Wenn du z.B. einen Knopf in deine Szene baust, der eine Tür öffnet, dann willst du da kein Event dazwischenknallen. Es ist in deinem Interesse, dass es offensichtlich ist, welche Tür der Knopf öffnet. Events sind eher für die Fälle, wo Auslöser und Beobachter (also die, die auf das Event reagieren) nicht wirklich etwas miteinander zu tun haben. Ein Beispiel dafür wäre ein Game Over-Event, wo der Auslöser (z.B. die sterbende Spielfigur oder der abgelaufene Timer) nichts mit den Beobachtern (also dem Game Over-Bildschirm oder dem Highscore-System) zu tun haben. Letztenendes löst das eine das andere aus, aber diese Verbindung geht keinen von beiden etwas an.

So nebenbei: Soda hat eine ScriptableObject-Klasse, mit der du ein GameObject samt component cache referenzieren kannst, um dann damit von irgendwo anders aus zu arbeiten. Das wäre neben direkten Drag and Drop innerhalb der Szene, Events und globalen ScriptableObject-Variablen ein weiterer Weg. Wann welches davon sinnvoll zu verwenden ist, ist gar nicht so leicht, aber deshalb habe ich die detaillierte Anleitung geschrieben, die dem Paket beiliegt :)

vor 9 Stunden schrieb TheOnlyOne:

Und zu dem Asset frage ich mich ob man mit dem einen Ereignis weitere Ereignise auslösen kann?

Jap. GameEvents haben ein UnityEvent, in das du alles mögliche aus den Assets ziehen kannst. Du kannst auch ein GameObject in die Szene packen, das auf ein Event mit dem Auslösen eines anderen Events reagiert, wenn diese Kette nicht permanent, sondern nur in bestimmten Situationen vorhanden sein soll.

Share this post


Link to post
Share on other sites
vor 21 Stunden schrieb Sascha:

Danke schonmal für's Feedback!

 Events sind eher für die Fälle, wo Auslöser und Beobachter (also die, die auf das Event reagieren) nicht wirklich etwas miteinander zu tun haben.

Also wenn ich zum Beispiel Fische im Wasser habe, die einfach zur Dekoration da sind und zudem noch spielerisch Objekte verfolgen welche sich im Wasser bewegen, somit dem Spieler auch, falls er im Wasser ist, haben sonst nichts mehr mit dem Spieler zutun. Und jetzt möchte ich eine weitere Funktion für Fische hinzufügen, sobald der Spieler hochspringt aus dem Wasser, sollten die Fische sich erschreckend von dem Spieler wegfliehen.

Und jetzt die Frage: wie würdest du es auf meiner Stelle lösen, für Sprung ein Event anlegen(auch wenn ich sonst nichts mehr plane irgendwas vom Sprung abhängig zu machen, was nicht zum Spieler gehört), oder sagen: "ok, da es nur eine kleine Funktionalität ist, verbinde ich die Fische mit dem Spieler Script und rufe fischewegflehen Funktion aus dem Spieler Sprung Funktion aus und gut ist es"?

Share this post


Link to post
Share on other sites

Ist die Dokumentation auch öffentlich zugänglich, so dass man sich erstmal einen Überblick verschaffen kann?

Share this post


Link to post
Share on other sites
Am 26.7.2019 um 20:18 schrieb TheOnlyOne:

Also wenn ich zum Beispiel Fische im Wasser habe, die einfach zur Dekoration da sind und zudem noch spielerisch Objekte verfolgen welche sich im Wasser bewegen, somit dem Spieler auch, falls er im Wasser ist, haben sonst nichts mehr mit dem Spieler zutun. Und jetzt möchte ich eine weitere Funktion für Fische hinzufügen, sobald der Spieler hochspringt aus dem Wasser, sollten die Fische sich erschreckend von dem Spieler wegfliehen.

Und jetzt die Frage: wie würdest du es auf meiner Stelle lösen, für Sprung ein Event anlegen(auch wenn ich sonst nichts mehr plane irgendwas vom Sprung abhängig zu machen, was nicht zum Spieler gehört), oder sagen: "ok, da es nur eine kleine Funktionalität ist, verbinde ich die Fische mit dem Spieler Script und rufe fischewegflehen Funktion aus dem Spieler Sprung Funktion aus und gut ist es"?

Moin... sorry für die späte Antwort, hab deinen Post irgendwie übersehen... Dafür würde ich ein Event anlegen. Eben weil das Springen der Fische kein Teil der Definition der Spielfigur ist. Die Figur funktioniert bestimmt auch einwandfrei, ohne dass da irgendwo definiert ist, was ein Fisch ist. Und auch wenn es keine Fische in der Szene gibt. Und was das Springen der Fische angeht: Was das auslöst, ist auch kein Teil der Definition eines Fisches. Das Springen könnte ja auch genausogut von etwas anderem ausgelöst werden.

Anders wäre es, wenn du da mehr Semantik im Fisch-Sprung hättest. Wenn nur Fische in einem bestimmten Radius um den Spieler springen sollen, oder wenn rote Fische auf den einen Spieler und blaue Fische auf den anderen reagieren sollen... da kann man sich das nochmal überlegen, das anders anzugehen.

Am 29.7.2019 um 08:12 schrieb devandart:

Ist die Dokumentation auch öffentlich zugänglich, so dass man sich erstmal einen Überblick verschaffen kann?

Ich hab's gerade einfach mal hochgeladen: http://13pixels.de/pages/assetstore/soda/documentation/annotated.html

  • Like 1

Share this post


Link to post
Share on other sites

Glückwunsch für den neuen AssetStore Packet. 

Ich persönlich bin nicht so der Fan davon (bezogen auf das Video) und ich meine  das gab es frei zu downloaden. Aber wenn ich mal sowas brauche mache ich passend zum Objekt. Beispiel passend zu meinem Projekt, Health, Shield.. (siehe unten) alles in einem ScriptableObject und das benutze ich das als Kommunikations (Ja Events gibt es da auch). 

Ich benutze sehr selten mittlerweile Singletons. Nur bei Komplexen ein System Sachen die einmal da sind (Beispiel mein InputReader Klasse) oder Kleinigkeiten wie (public static) Player.localPlayer.

Bei komplizierteren Sachen stell ich mir das aber harter vor.
Ich frage mich zum Beispiel, wie man das verwenden könnte, wenn man jetzt kleinere Minibosse hat, die ab und zu da sind dann im HUD einen Healthbar anzeigen möchte. Muss ich für jeden SO Asset erstellen? Gut es könnten ja alle, den einen Asset teilen, aber was wenn mal zwei Minibosse gleichzeitig gibt und ich will beide Healthbars anzeigen lassen.. Dann lässt sich das nicht so leicht teilen.

Ein Beispiel wie ich zum Beispiel mein Health  und Shield UI update.

[CreateAssetMenu]
public class DamageEventSO : ScriptableObject
{
    public EventValue<float> Health;
    public EventValue<float> Shield;
}

public struct EventValue<T>
{
    public UnityAction<T> OnValueChanged;

    T value;
    public T Value
    {
        get => value;
        set
        {
            this.value = value;
            OnValueChanged?.Invoke((T)(object)this.value);
        }
    }
}

So wie man sieht, ist das hier generic und brauche da nicht floats, ints oder sonst ähnliches.

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...

×
×
  • Create New...