Jump to content
Unity Insider Forum

Abhängigkeiten zwischen Gameobjects sauber lösen


Damon93

Recommended Posts

Guten Abend zusammen :)  Nach langer Zeit komme ich auch mal wieder mit einer Frage.

Zum Szenario. Ich habe in meiner Scene n Unternehmen. Jedes Unternehmen kann n Einwohner in einer Anstellung haben. Die Unternehmen zahlen den Angestellten ein Gehalt x.

Um meine Einwohner/Angestellten zu verwalten habe ich mir überlegt ScriptableObjects zu verwenden. So kann ich properties wie firstName, bankAccount, salary etc. meiner Meinung nach einfach verwalten.

Jetzt kann es in meinem Spiel passieren, dass bspw. ein Unternehmen durch ein Ereigniss, dass Zufällig im Spiel auftreten kann, Gehaltskürzungen vornimmt.

Wie wäre jetzt ein sauberer Weg, dieses GehaltskürzungsEvent an die betroffenen Angestellten zu senden? Muss mein Unternehmen eine Liste von Gameobjects (Einwohnern) halten um zu wissen welche Einwohnener auch Angestellte sind? Oder kann man das irg. wie über Actions machen?

Dazu möchte ich erwähnen, dass ich 1 ScriptableObject habe -> EinwohnerScriptableObject

Dies erstelle ich nun n mal für jeden Einwohner und passe die properties wie firstName etc. an.

Kann ich zur Laufzeit wenn das GehaltskürzungsEvent auftritt, Werte wie salary aus dem ScriptableObject ändern, sodass diese auf Dauer geändert bleiben?

 

Vllt noch kurz zu meinem Denkproblem :D -> Angenommen ich habe 100 Unternehmen und 10000 ANgestellt, dann müsste ich ja für jedes Unternehmen die Angestellten in die Liste von Gameobjects packen um eine Referenz auf den Angestellten zu bekommen. Das erscheint mir nicht nur unheimlich kompliziert, sondern auch mühsam und fehleranfällig.

 

Ich hoffe ich konnte mein Problem gut schildern und freue mich auf feedback :) 

Link zu diesem Kommentar
Auf anderen Seiten teilen

Hallo

 

Also entweder haben die Angestellten ja gespeichert, bei welchem Unternehmen sie sind oder die Unternehmen haben gespeichert, wer bei Ihnen arbeitet. Beim zweiten Fall kann das betroffene Unternehmen ja einfach seine Angestellte informieren und bei denen eine entsprechende Funktion aufrufen. 

Wenn die Angestellten sich ihr Unternehmen gemerkt haben, dann sende doch den Event, dass ein Unternehmen Lohnkürzungen vornimmt und entweder gibst du dem Event das Unternehmen als Parameter mit und iterierst dann durch alle Angestellten und schaust, ob deren Unternehmen mit dem des Events übereinstimmt. Wenn dies der Fall ist, rufst die Lohnkürzungsfunktion auf. Du kannst auch den Event ohne Parameter feuern und dabei eine globale Variable (kann natürlich auch So sein) setzen, in welchem das entsprechende Unternehmen hinterlegt wird. So mache ich das meist. 

 

Christoph  

Link zu diesem Kommentar
Auf anderen Seiten teilen

vor 3 Stunden schrieb Damon93:

Um meine Einwohner/Angestellten zu verwalten habe ich mir überlegt ScriptableObjects zu verwenden. So kann ich properties wie firstName, bankAccount, salary etc. meiner Meinung nach einfach verwalten.

 

vor 3 Stunden schrieb Damon93:

Dies erstelle ich nun n mal für jeden Einwohner und passe die properties wie firstName etc. an.

ScriptableObjects sind dafür da, um etwas im Editor zu definieren, das dann im Spiel landet. Wenn du irgendetwas hast, das nur zur Laufzeit existiert, dann bringt es dir keine Vorteile, dieses Ding von einem SO repräsentieren zu lassen. ScriptableObjects zur Laufzeit zu erzeugen, anstatt sie im Editor anzulegen, ist ein recht klares Zeichen dafür, dass was nicht ganz rund läuft.

Nimm stattdessen einfach ganz normale Objekte. ScriptableObjects nehmen einfach nur mehr Arbeitsspeicher weg.

Wobei du auch nicht unbedingt für jeden Einwohner gleich ein ganzes Objekt brauchst. Wenn du einfach pro Firma x Angestellte hast, dann kann es auch reichen, ein int in das Firma-Objekt zu packen. Dann wird die Berechnung irgendwelcher Kosten auch viel harmloser. Individuelle Sachen wie Namen kannst du dann immer noch prozedural generieren, ohne sie zu speichern.

Davon abgesehen...

vor 3 Stunden schrieb Damon93:

dann müsste ich ja für jedes Unternehmen die Angestellten in die Liste von Gameobjects packen um eine Referenz auf den Angestellten zu bekommen.

Ist jeder angestellte ein GameObject? Da hast du mit 10.000 Stück sowieso eigentlich direkt verloren. Für so eine Menge von Akteuren brauchst du ECS.

Wenn es aber nur um simple Datenobjekte geht, dann kannst du durchaus ein paar Tausend Stück haben... und die auch in eine Liste tun. Aber wie gesagt, das muss vielleicht gar nicht unbedingt sein.

Zum Thema Events: Events sind dazu da, dass der Auslöser und der Reagierende sich nicht kennen. Wenn der Spieler stirbt löst er ein Event aus, und als Reaktion erscheint ein Game-Over-Bildschirm. Dass das Spieler-Leben-System und das Game-Over-Bildschirm-System sich nicht kennen, ist eine gute Idee. In deinem Fall aber ist es durchaus logisch, dass die Firma ihre angestellten kennt. Wie @chrische5 also schon sagt: Da kann die Firma einfach über die Liste iterieren, die sie sowieso schon rumliegen hat. Und eine Liste von Firmen, über die man iteriert, um über die Gehaltskürzung zu informieren, klingt auch erst mal nicht falsch.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Super, danke für eure beiden Antworten.

Zitat

ScriptableObjects sind dafür da, um etwas im Editor zu definieren, das dann im Spiel landet.

Habe die Teile noch nicht so richtig verstanden. In vielen Tutorials werden die als das ultimative mittel für die Game Architektur beschrieben... daher dachte ich, es ist eine gute Idee, all meine Einwohner damit zu erzeugen. 

Zitat

Ist jeder angestellte ein GameObject?

Ich plane das aktuell so, dass ich eine Stadt habe, mit Häusern und in jedem haus n Personen leben. Diese Personen/Einwohner haben natürlich auch einen Job bei einem der n Unternehmen innerhalb der Stadt.

Die Einwohner selbst werden vom Spieler nicht gesehen (wird keine Modelle für sie geben). Sie "existieren" also so gesehen erstmal nicht. Dennoch haben Sie Namen, Einkommen etc. Dementsprechend vermute ich, benötige ich ein EmptyGameobject für jeden Einwohner oder?

Falls ja, dann muss ich in meinem UnternehmensScripts eine Liste mit Angestellten führen und diese Liste über den Inspektor mit den EinwohnerEmptyGameobjects befüllen oder? Damit die connection zwischen Unternehmen und Angestelltem da ist.

Und jetzt hatte ich mir halt gedacht, dass es vllt auch einen schöneren Weg gibt, diese Einwohner <-> Unternehmens Beziehung abzubilden. 

EDIT: Während ich den Text gerade schreibe, fällt mir auf, dass ich das Ganze in meiner Vorstellung über Delegates lösen wollte. Also Unternehmen kennen Angestellte nicht. Und Angestellte reagieren auf Events vom Unternehmen. Je mehr ich aber drüber nachdenke und auch über eure beiden Kommentare, macht es super viel Sinn, dass das Unternehmen die Angestellten einfach kennt... machts irg. wie auch einfacher :) 

Danke euch zwei. ich werde mal weiter programmieren und schauen ob ich nochmals nen Knoten im Hirn bekomme ;) 

Link zu diesem Kommentar
Auf anderen Seiten teilen

vor 10 Stunden schrieb Damon93:

Die Einwohner selbst werden vom Spieler nicht gesehen (wird keine Modelle für sie geben). Sie "existieren" also so gesehen erstmal nicht. Dennoch haben Sie Namen, Einkommen etc. Dementsprechend vermute ich, benötige ich ein EmptyGameobject für jeden Einwohner oder?

Nö. GameObjects erlauben dir, Dinge in deiner Szene darzustellen. Ein GameObject brauchst du daher nur, wenn du einen Akteur in deiner Szene haben willst, der Einfluss auf Rendering (also "ist sichtbar" oder Lichtquelle oder so), Physik (Collider oder sogar etwas das sich bewegt) oder Sound haben soll.

Deine Beschreibung klingt sehr stark danach, als wäre das nicht der Fall. Deine Einwohner sind nur Zahlen auf dem Papier, und können dem entsprechend auch abstrakt in deinen Daten dargestellt werden. Wie ich oben meinte, vermute ich, dass du nicht nur kein GameObject, sondern vermutlich nicht einmal ein (normales) Objekt pro Einwohner brauchst. Denk an Cookie Clicker: Da hast du sicherlich auch nicht Milliarden von Keks-Objekten. Und wäre es in Unity implementiert, hättest du schon gar nicht Milliarden GameObjects.

Falls du ungefähr weißt, wie Borderlands funktioniert: Wäre das in Unity implementiert, wären Waffen, die auf dem Boden liegen, GameObjects. Dein Inventar allerdings, in dem du ein paar dutzend von den Dingern hast, wären normale Objekte, in denen die Daten der jeweiligen Waffe stehen.

Ich nehme an, dass @chrische5 dasselbe sagen wollte: "Nur, wenn es eine Repräsentation in der Spielwelt gibt, ...".

Ich denke, die List<Worker> kann funktionieren, aber du könntest es meiner Meinung nach noch viel sparsamer mit int workerCount implementieren.

vor 10 Stunden schrieb Damon93:

Habe die Teile noch nicht so richtig verstanden. In vielen Tutorials werden die als das ultimative mittel für die Game Architektur beschrieben... daher dachte ich, es ist eine gute Idee, all meine Einwohner damit zu erzeugen. 

Jein. Die Dinger sind unheimlich wichtig, um etwas sauberes zu bauen, aber deshalb nicht überall sinnvoll. Wie gesagt: Sie sind dafür da, Daten für das Spiel im Editor zu definieren. Aber halt ohne das in einer Szene oder einem Prefab zu tun.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Zitat

Wenn es Repräsentation in der Spielwelt gibt, brauchst du auch GO

Zitat

Ein GameObject brauchst du daher nur, wenn du einen Akteur in deiner Szene haben willst, der Einfluss auf Rendering (also "ist sichtbar" oder Lichtquelle oder so), Physik (Collider oder sogar etwas das sich bewegt) oder Sound haben soll.

Also verstehe ich das richtig: Da meine Einwohner zu keiner Zeit durch ein Modell sichtbar sind, brauche ich keine GameObjects? Was ich machen möchte ist, ich habe Häuser in denen Einwohner leben, und wenn der Spieler nun über ein Haus hovert oder drauf klickt, dann solll da nen Fenster auf gehenb wo steht hier wohnt XY, XY verdient Z Dollar und arbeitet bei ABC Firma.

Dies wäre alles was von Einwohnern so gesehen sichtbar ist. Wie gesagt die Properties der Einwohner können sich dennoch verändern.

Mir fehlt hier so ein bisschen die Instanziierung der Einwohner, wenn ich kein GO verwende. Denn die Alternative wäre ja, ich Instanziiere in jedem UnternehmenScript, innerhalb der Awake oder Start Methode eine Liste mit newWorker(). Das würde bedeuten, dass ein Einwohner fest an einem Unternehmen hängt, was ich so ja nicht möchte. Oder?.

Denn Angenommen ein Einwohner verliert seinen Job, oder wechselt den Job, dann stoße ich hier doch auf ein Problem... oder? 

 

Nochmals Danke für euren Input! Hilft mir sehr :) 

 

Link zu diesem Kommentar
Auf anderen Seiten teilen

vor 5 Stunden schrieb Damon93:

Also verstehe ich das richtig: Da meine Einwohner zu keiner Zeit durch ein Modell sichtbar sind, brauche ich keine GameObjects?

Naja, "sichtbar" ist eine der Arten, in der man in einer Szene eine Rolle erfüllen kann. Eine unsichtbare Wand, um den Spieler daran zu hindern irgendwo lang zu hüpfen, oder eine AudioSource, aus der Windgeräusche kommen, dürfen genauso in die Szene. Aber davon abgesehen: Genau.

vor 5 Stunden schrieb Damon93:

Denn die Alternative wäre ja, ich Instanziiere in jedem UnternehmenScript, innerhalb der Awake oder Start Methode eine Liste mit newWorker(). Das würde bedeuten, dass ein Einwohner fest an einem Unternehmen hängt, was ich so ja nicht möchte. Oder?.

Nö. Ein Objekt gehört niemals einem anderen Objekt. Wir lassen Structs da gerade mal außen vor, aber Objekte sind auf dem "Heap", einer Datenstruktur, die dein Spiel im Arbeitsspeicher anlegt. Und die ist genau so organisiert, wie der Name suggeriert: Es ist ein "Haufen". Da sind einfach alle Objekte draufgeschmissen und fertig. Jeder kann dein Objekt referenzieren, jeder kann damit arbeiten. Das einzige, was hier einschränkend wirkt, ist die Kontrolle über die Referenz. Wenn irgendein Code nicht weiß, an welcher Speicheradresse dein Objekt ist, dann kann er es auch nicht finden. Sobald du die Referenz aber hast, kann dein Code alles mit dem Objekt tun, was man eben so damit tun kann.

Auch, wenn das Objekt, dass dein Einwohner-Objekt erzeugt hat, aufhört zu existieren, ist das egal. So eine Art Verbindung zwischen einem Objekt und wo es herkommt, oder überall schonmal benutzt wurde, gibt es einfach nicht.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Ich muss jetzt einfach nochmal fragen, weil so ganz 100% habe ich es glaube ich noch nicht verstanden.

1. Ich habe die Option, GO's oder Empty GO's zu erstellen und dort mein EinwohnerScript als Component zu verwenden. Dann wird sobald ich den Start Knopf in Unity drücke eine Instanz vom EinwohnerScript erstellt und ich habe z.B. 20 Einwohner (20 GO's) in meiner Stadt, auf die ich immer ganz entspannt zugreifen kann (über das jeweilige GO).

2. Ich kann das EinwohnerScript ohne MonoBehaviour erstellen. Wenn ich nun den Start Knopf drücke, passiert erstmal gar nichts. Mein EinwohnerScript wird nicht instanziert. Ich muss es also erst in irg. einem Monobehaviour Script instanzieren. Zum Beispiel könnte ich ein GameManger GO erstellen und in dem Instanziere ich nun diese 20 Einwohner innerhalb der Awake oder Start Methode. Wenn ich nun aber in irg. einem anderen Script diese Einwohner verwenden möchte. Dann muss dieses auf das GameManager MonoBehaviour zugreifen, das meine Einwohner instanziiert hat. Das heißt, das MonoBehaviour, das meine Einwohner instanziiert hat, ist sozusagen der Parent von diesen Einwohnern, und ich komme nur über dies MonoBehaviour an die Einwohner drann (das meinte ich mit, die Einwohner gehören dem Monobehaviour Objekt).

 

Vllt habe ich irg. wo einen dicken Knoten in meinem Hirn. Falls dem so ist, würde ich mich freuen wenn Ihr den lösen könntet :D Falls ich aber mit meinen beiden oben genannten Optionen den Nagel auf den Kopf getroffen habe, dann würde ich mich glaube ich eher für die Gameobject (1) entscheiden, da ich das Managen dieser Einwohner Instanzen damit komfortabler finde (kann dann über den Inspector properties verändern etc.). 

Und auch hier gilt wieder, falls ihr Option 2 besser findet, gerne sagen warum. Habe Unity bisher immer nur relativ Oberflächlich verwendet und möchte da jetzt endlich mal nen bisschen tiefer durchsteigen :) 

Link zu diesem Kommentar
Auf anderen Seiten teilen

Du könntest doch mit der Generic-Function "List<T>" eine Liste von Personen erstellen. Einwohner oder Mitarbeiter. 

public class Mitarbeiter
{
    public string Vorname { get; set; }
    public string Nachname { get; set; }
    public int Alter { get; set; }
}

List<Mitarbeiter> mitarbeiterListe = new List<Mitarbeiter>();

Mit Add kannst du neue Personen einfügen

Mitarbeiter m = new Mitarbeiter { Vorname = "Max", Nachname = "Mustermann", Alter = 30 };
mitarbeiterListe.Add(m);

oder entfernen

mitarbeiterListe.Remove(m);

oder alle Personen ausgeben

foreach (Mitarbeiter m in mitarbeiterListe)
{
    Debug.Log("{0} {1} ({2} Jahre alt)", m.Vorname, m.Nachname, m.Alter);
}

So brauchst du keine GO...hast aber eine Liste mit Personen. Du kannst auf diese Zugreifen und machen was du willst.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Zitat

Ich denke du solltest weniger in Unity tiefer einsteigen und mehr in die Programmierung :D 

Bin seit 8 Jahren als Softwareentwickler im Bereich Backend-Entwicklung (Spring Boot mit Java und Kotlin tätig), sowohl als DevOps Engineer. Ich glaube an meinen Programmierfähigkeiten scheitert es nicht :P

 

Zitat
public class Mitarbeiter
{
    public string Vorname { get; set; }
    public string Nachname { get; set; }
    public int Alter { get; set; }
}

List<Mitarbeiter> mitarbeiterListe = new List<Mitarbeiter>();

Wie man Listen erstellt und befüllt ist mir wie gesagt bekannt :) Hier liegt nicht mein "Problem".

Ich werde einfach mal ein bisschen präziser, da ich glaube mich noch nicht klar genug ausgedrückt zu haben -> Da jetzt tipps rein kommen, wie ich Listen befülle^^

Also ich habe eine Klasse Einwohner. Nichts besonderes. Diese kann ich in Unity nun auf verschiedene Arten verwenden.

public class Einwohner {

	public string Vorname {get; set;}
	//.. Und weitere properties

	
	public void GehaltErhoehen() {
		//ToDo: Implement
	}
	//... und weitere Methoden
}

Ich könnte eine andere Klasse haben z.B: GameManager. GameManager ist ein MonoBehaviour, heißt, er hängt an einem GO

public class GameManager : MonoBehaviour {

	public List<Einwohner> myList = new List()
	//.. Und weitere properties

	
	void Start(){
    	myList.add(new Einwohner())  
    }
}

Im GameManager instanziiere ich nun meine Einwohner. Denn wenn ich das Spiel starte, wird die Start() Methode vom GameManger gecalled und eine Liste mit einem Einwohner erzeugt. Mein GameManager hält nun also eine Liste mit X Einwohnern. 

Die zweite Option wäre, dass meine Einwohner Klasse selber von MonoBehaviour erbt. Somit würde die Einwohner Klasse als Componente auf einem GO liegen. Ich könnte jetzt also im Inspector die Properties wie den Vornamen etc. anpassen. Um den Einwohner einem Unternehmen zu zuweißen könnte ein Script so aussehen:

public class Unternehmen : MonoBehaviour {
	// Die Einwohner GO würde ich nun über den Inspector per Drag and Drop dieser Liste hinzufügen. Ich benötige also kein new keyword mehr.
	public List<Einwohner> myList = new List()
  
  void Start() {
  	//Hier könnte ich mir nun DInge ausgeben lassen   
      myList.ForEach((einwohner) => {
      	print(einwohner.Vorname())
      })
  }
  
}

@gombolo du sagst nun:

Zitat
foreach (Mitarbeiter m in mitarbeiterListe)
{
    Debug.Log("{0} {1} ({2} Jahre alt)", m.Vorname, m.Nachname, m.Alter);
}

Wo würde denn diese foreach-Loop bei dir liegen? In einem Script das von MonoBehaviour erbt? 

Aber zurück zu meiner Frage.

Ich habe jetzt 2 Optionen aufgezeigt wie ich EInwohner verwalten könnte. einmal per MonoBehaviour an GO's drann, und einmal in einem MonoBehaviour (GameManager).

Und hier kommt meine Frage, sind dies die einzigen 2 Möglichkeiten in Unity, wie ich Instanzen verwalten/ instanziieren kann? Am Ende muss ich ja immer auf einem MonoBehaviour eine Instanz von etwas erstellen. Oder?

 

Denn angenommen, ich hätte ein weiteres Script, das nicht von MonoBehaviour erbt, und auch sonst nichts tut. Es liegt einfach nur so da^^

public class EinwohnerManager {

	public List<Einwohner> myList = new List()
	//.. Und weitere properties

	// Hier befülle ich via constructor meine Liste.
	void EinwohnerManager(){
    	myList.add(new Einwohner()) 
      	myList.add(new Einwohner())  
    }
}

Jetzt hätte ich in der Theorie in diesem Script meine Einwohner liegen. Meines Wissenstandes nach, wird der Constructor aber nie gecalled. Dieses Script müsste entwader ein MonoBehaviour sein, oder von einem anderen Script, welches ein MonoBehaviour ist instanzieert werden. Oder?

 

Link zu diesem Kommentar
Auf anderen Seiten teilen

vor 19 Minuten schrieb Damon93:

Bin seit 8 Jahren als Softwareentwickler im Bereich Backend-Entwicklung (Spring Boot mit Java und Kotlin tätig), sowohl als DevOps Engineer. Ich glaube an meinen Programmierfähigkeiten scheitert es nicht :P

 

🙄 ok... 😁

Ich blicke trotzdem nicht ganz durch, aber ich kann dir sagen wie ich das gemacht haben. Hatte auch viele Objekte und ich habe diese in einem "GameManager" (meiner nannte sich ObjectManager) verwaltet. Verwaltet wurde eine Klasse die nicht von MonoBehaviour geerbt hatte. Es musst nur Daten speichern.

Was ich noch nicht ganz verstehe. In "Unity-Script (C#)" kann man doch ganz normale Klassen verwenden die dann auch so reagieren wie "normale" Klassen reagieren. Also auch der Konstruktor wird aufgerufen sobald du den new-Operator aufrufst.

Link zu diesem Kommentar
Auf anderen Seiten teilen

vor 4 Stunden schrieb Damon93:

Am Ende muss ich ja immer auf einem MonoBehaviour eine Instanz von etwas erstellen. Oder?

Nein :)

Dein Projekt ist auch nur ein ganz normales C#-Programm, das von der darunter liegenden C++-Engine gestartet wird. Du hast keinen Zugriff auf die übliche Main-Methode und einen ganzen Haufen Engine-interner Dinge, aber abgesehen davon hast du da nicht so wirklich nennenswerte Einschränkungen.

Wenn du diesen Satz also so meinst, dass der Code zum Erstellen von Objekten in einem MonoBehaviour stecken muss, dann: Nein. Objekte können Objekte können Objekte erstellen. Gar kein Problem.

Wenn du den Satz aber so meinst, dass der initiale Impuls, dass irgendetwas passiert, aus Unity heraus kommen muss, dann hast du damit sogar Recht. Wenn du daraus aber wiederum ableitest, dass das in einem MonoBehaviour passieren muss, dann stimmt die Behauptung auch wieder nicht.

Unity hat einen solchen Impuls, der einfach nur zum Programmstart irgendeinen Code ausführt - ähnlich einer Main-Methode. Dafür brauchst du dieses Attribut:

[RuntimeInitializeOnLoadMethod]
private static void InitializeStuff()
{
  Debug.Log("Hello, World!");
}

Das kannst du über eine parameterlose, statische Methode in einer beliebigen Klasse packen und ab dafür. Das Attribut hat auch noch einen optionalen Parameter, mit dem du bestimmen kannst, ob das vor dem Laden der ersten Szene passieren soll oder danach... oder noch woanders.

In dieser Methode kannst du dann auch wunderbar auch verschiedene Events subscriben, z.B. auf das Wechseln zu einer anderen Szene. Du kannst auch mit dem PlayerLoopSystem deine eigene Update-Methode schreiben, die kein MonoBehaviour braucht, wobei es für simple Fälle meiner Meinung nach entspannter ist, einfach ein Gameobject zu bauen.

Nachdem all das gesagt ist, finde ich es aber wichtig, zu erwähnen, dass das nicht heißt, dass du ab jetzt MonoBehaviour meiden solltest, solange etwas nicht sichtbar ist oder so. Ein GameObject definiert ein Stück weit, wie eine Szene funktioniert. Und das darfst du auch genau so nutzen.

So als Beispiel: Ich habe ein Beispiel-Projekt für Soda (ein Asset-Store-Paket von mir) gebaut. Als Hinweis: Gerne anschauen, ich benutze es auch als Best Practices-Showcase, aber ohne Soda wird es nicht kompilieren.

Dort habe ich jedenfalls ein Musik-System. In diesem System benutze ich das [RuntimeInitializeOnLoadMethod]-Attribut, um direkt bei Spielstart ein GameObject zu erzeugen. Dieses mache ich mit HideFlags unsichtbar, damit es im Editor nicht weiter auffällt, und mit DontDestroyOnLoad mache ich es "unverwundbar" gegen Szenenwechsel. Damit habe ich ein (wenn man nicht danach sucht...) unsichtbares GameObject, das von Anfang bis Ende der Laufzeit existiert. Diesem GameObject gebe ich eine AudioSource, das die Hintergrundmusik abspielt.

Nun habe ich aber auch eine Komponente, die einen AudioClip referenzieren kann und die sich, solange sie enabled ist, in eine Liste einträgt. Wann immer sich eine solche Komponente einträgt, wird der AudioClip des letzten Elements der Liste von dieser AudioSource abgespielt. Wenn ich also eine neue Szene mache und da ist nichts drin, dann habe ich da Musik laufen, sofern der Player da etwas brauchbares in der Liste hat.

Und damit komme ich endlich zu meinem Punkt: Wenn ich eine Musik-Komponente in meine leere Szene packe, dann habe ich eine leere Szene, die ihre eigene Musik vom globalen Musik-Player abspielen lässt. Diese Komponente ist für den Spieler unsichtbar, sie stellt keine unsichtbare Wand dar, gar nichts. Und trotzdem hat sie, in der Szene und als MonoBehaviour, ihre Daseinsberechtigung, weil sie dazu beiträgt, zu definieren, was genau in dieser Szene passiert.

Es ist also völlig okay, eine MonoBehaviour-Klasse zu schreiben, um irgendwelche Dinge zu initialisieren oder um Daten einzutragen, die in der Szene relevant sein können.

Es ist aber trotzdem sehr empfehlenswert, sich von der Idee zu lösen, die Unity einem initial leider vermittelt: Dass alles irgendwie in MonoBehaviours passieren muss.

Link zu diesem Kommentar
Auf anderen Seiten teilen

@gombolo Aber dein ObjectManager ist ein MonoBehaviour nehme ich an?

 

Zitat

Wenn du den Satz aber so meinst, dass der initiale Impuls, dass irgendetwas passiert, aus Unity heraus kommen muss, dann hast du damit sogar Recht. Wenn du daraus aber wiederum ableitest, dass das in einem MonoBehaviour passieren muss, dann stimmt die Behauptung auch wieder nicht.

Now we are talking :D !

Danke @Sascha meine Eindruck war tatsächlich der, dass der initiale Impuls aus einem MonoBehaviour kommen muss.

[RuntimeInitializeOnLoadMethod]

war mir bis jetzt noch nicht bekannt.

Und nein, ich werde natürlich MonoBehaviours weiterhin verwenden :)  Mir ist nur wichtig, alle Möglichkeiten zu kennen mit den Vor und Nachteilen. Wie es in der Softwareentwicklung halt so ist, viele Wege führen zum Ziel, manche sind sch****, manche sind gut, und manche sind perfekt... aber viele führen ans Ziel :D 

Wie gesagt möchte ich ein bisschen tiefer Eintauchen, und als ich mit Unity vor ein paar Jahren angefangen habe (mit einer etwas längern Pause - bis jetzt) wurde so ziemlich alles mit MonoBehaviours gemacht (in so ziemlich allen Tutorials die es vor ca. 7 Jahren so gab haha), daher nochmals danke für deinen ausführlichen Beitrag. Jetzt habe ich ein paar Buzzwords, mit denen ich meine Recherche fortsetzen kann.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Zitat

...aber jetzt verstehe ich deine Problematik besser und verstehe deinen Gedankengang und muss dir Recht geben.  Es ist eine Überlegung wert.....🙄

Tatsächlich hatte ich während dem Verlauf dieses Threads ein paar Gedankensprünge gehabt - was vermutlich der Grund dafür war, weshalb ich meine Thematik nicht so perfekt schildern konnte :P
 

Aber Ende gut, alles gut :D

Link zu diesem Kommentar
Auf anderen Seiten teilen

Archiviert

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

×
×
  • Neu erstellen...