Jump to content
Unity Insider Forum

Awake und Start


Tiwaz

Recommended Posts

Moin,

 

Auch wenn ich mir schon ziemlich viel zu dem Thema durchgelesen hab aber irgendwie erschließt sich mir der Sinn von Awake nicht ganz, würd das aber gern endlich mal verstehen ^^

Ich hab bisher immer alles in die Start() geschrieben und ich hatte wirklich noch NIE Probleme damit, von daher hab ich mich auch nicht wirklich um Awake gekümmert..

 

Also ich weiß, dass Awake() immer aufgerufen wird sobald alle Objekte initialisiert wurden und danach die Start(), sofern das Objekt enabled ist.

Auch weiß ich wann man die Awake() Methode benutzen sollte, allerdings hab ich bis jetzt nie wirklich verstanden was das für einen Unterschied macht eine Initialisierung in die Awake() oder am Anfang der Start() zu schreiben.

 

Also worin liegt der Unterschied zwischen:

 

void Awake(){
  komponente = Transform.Find("Komponente");
}

void Start(){
  komponente.MachEtwas();
}

 

und

 

void Start(){
  komponente = Transform.Find("Komponente");

  komponente.MachEtwas();
}

Link zu diesem Kommentar
Auf anderen Seiten teilen

Also ich weiß, dass Awake() immer aufgerufen wird sobald alle Objekte initialisiert wurden und danach die Start(), sofern das Objekt enabled ist.

 

Das wusste ich schon aber ich bin trotzdem noch nie über eine Situation gestolpert in der man diesen halben Frame Initialisierungsunterschied wirklich brauchen würde. Von daher versteh ich auch noch nicht wo dann der Sinn liegt weil ich mir einfach nix vorstellen kann wo das essentiell ist oder überhaupt nen Unterschied macht.

Denn wenn ich sagen wir mal 4 Scripts habe die von einander was wissen müssen und ich die in einer ganz bestimmten Reihenfolge initialisieren muss, dann hilft mir ja die Awake auch nichts, da die Komponenten so initialisiert werden wie sie geladen wurde und ich brauche trotzdem die Script Execution Order.

Oder?

 

Es wäre super mal ein Code Snippet zu sehen wo die Awake wirklich benötigt wird damit das funktioniert.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Das wusste ich schon aber ich bin trotzdem noch nie über eine Situation gestolpert in der man diesen halben Frame Initialisierungsunterschied wirklich brauchen würde. Von daher versteh ich auch noch nicht wo dann der Sinn liegt weil ich mir einfach nix vorstellen kann wo das essentiell ist oder überhaupt nen Unterschied macht.

 

Bei einem einzelnen Objekt wirst du da auch keinen grossen Unterschied merken. Aber denk doch mal in mehreren Objekten. Zuerst initialisierst du ein paar Variablen in Awake, dann greifst du per Script und Start von einem anderen Objekt drauf zu. Und stellst so sicher dass die Variablen schon zur Verfügung stehen.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Ja aber stelle ich das nicht auch sicher wenn ich die Variablen einfach am Anfang der Start() initialisiere?

Ich meine da Start() ja sowieso nach Awake aufgerufen wird, kann ich mir doch auch hier sicher sein, dass das Objekt initialisiert wurde und ich darauf zugreifen kann.

Und wenn ich die Aktionen in die das referenzierte Objekt involviert ist immer am Schluss der Start() hinschreibe, müsste es doch auf das exakt gleiche rauskommen oder etwa nicht?

 

Könntest du mal irgendein konkretes Beispiel/eine konkrete Situation nennen wo es ohne Awake zu Problemen kommen würde?

Link zu diesem Kommentar
Auf anderen Seiten teilen

Hatte erst letztens den Fehler wieder, war aber Flüchtig weil ich's schnell getestet hatte.

 

Ich hab Sascha mal gefragt wie ich am besten ein Objekt einer Klasse initialisiere, die nicht statisch ist, aber trotzdem bloß einmal als Komponente in der Szene vorkommt, dabei hab ich dann zuerst in der Start das Objekt überall initialisiert : (ersetze die Code Tags wenn ich am PC bin, sorry)

 

public class MyClass : MonoBehaviour

{

public static MyClass myClass;

 

void Start ()

{

myClass = this;

}

}

 

 

public class Other : MonoBehaviour

{

private MyClass myClass;

 

void Start ()

{

myClass = MyClass.myClass;

}

}

 

 

Hierbei könnte es jetzt natürlich dazu kommen dass myClass noch gar nicht initialisiert wurde, also die Start zuerst aufgerufen wurde, die erst später initialisieren soll..

Ich hab mir aber im allgemeinen inzwischen angewöhnt die wichtigsten Objekte (Wie Klassen Instanzen) in der Awake und dann weitere Variablen erst in der Start zu initialisieren, so hat man das Problem aufjedenfall behoben, aber ob das eine gute Lösung ist weiß ich nicht wirklich ;)

Link zu diesem Kommentar
Auf anderen Seiten teilen

Und wenn ich die Aktionen in die das referenzierte Objekt involviert ist immer am Schluss der Start() hinschreibe, müsste es doch auf das exakt gleiche rauskommen oder etwa nicht?

 

 

Wie gesagt, du denkst hier immer noch in einem Objekt. Denk mal an mehrere Objekte und mehrere Scripte. Woher weisst du denn in welcher Reihenfolge die abgearbeitet werden?

 

Konkret fällt mir spontan grade nix ein, sorry. Ich hatte das zwar schon im praktischen Einsatz, da müsste ich aber erst mal kruschteln.

 

Letztenendes ist erlaubt was funktioniert. Und wenn du mit Start auskommst brauchst du halt kein Awake :)

Link zu diesem Kommentar
Auf anderen Seiten teilen

Denk mal an mehrere Objekte und mehrere Scripte. Woher weisst du denn in welcher Reihenfolge die abgearbeitet werden?

 

Ich bau mir ganz gern eine ItemDatenbank die eine Liste mit allen Items enthält.

Da hatte ich dann auch schon mal das "Problem" dass wenn Unity mein Inventar befüllen will aber ItemDatabase noch nicht ge"Start()"ed wurde, ich logischerweise Exceptions bekomme weil noch nix drin steht.

Da könnte ich mir vorstellen, dass die Initialisierung der ItemDatabase in der Awake() das vermeiden würde oder?

Bisher hat mir da die Script Execution Order Abhilfe geschaffen aber da ich das immer wieder verwende wäre es schon nett nicht bei jedem Projekt zuerst die SEO einstellen zu müssen ^^

 

Hierbei könnte es jetzt natürlich dazu kommen dass myClass noch gar nicht initialisiert wurde, also die Start zuerst aufgerufen wurde, die erst später initialisieren soll..

 

Kann das wirklich vorkommen?

Ich meine die Awake wird ja sogar noch früher als die Start() aufgerufen also müsste es hier (theoretisch) doch erst Recht zu Problemen kommen oder? ^^

Aber praktisch sollte das doch nie passieren können weil die Awake() doch erst aufgerufen wird sobald alle Objekte initialisiert wurden und dazu zählt auch, dass wiederum alle Komponenten initialisiert sind richtig?

Und da die static Variable direkt zum Script gehört und nicht zu einer Instanz müsste die doch direkt mit dem Script angelegt werden oder verstehe ich das falsch?

 

PS: Ich glaube ich komm gerade ziemlich Anti-Awake() rüber aber das bin ich eigentlich überhaupt nicht, ich weiß nur nicht wirklich was damit anzufangen bzw. weiß bis dato keine Situation wo es Funktionalität bietet die man mit der Start() auch problemlos erreichen kann.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Glaube da hast du mich etwas falsch verstanden , sicher existiert die statische Variable schon aber sie ist ja nur während der Runtime persistent, mit jedem Start hat sie ja bis zum Start Aufruf wieder den Wert null, was ich meine ist ja, dass das andere Script vielleicht nun als erstes mit der Start dran kommen würde, sprich es ruft auf myClass = MyClass.myClass während aus MyClass myClass vielleicht noch null ist (Etwas eindeutigere Namen wären vielleicht besser gewesen aber unterscheiden sich ja immerhin in Gross und klein Schreibung :D ) klar ist das nicht unbedingt nötig, man braucht ja kein neues Objekt und könnte, sobald man das Objekt braucht einfach sagen MyClass.myClass.MachIrgendwas aber ist gerade bloß als Beispiel gedacht...

Der Fehler würde ja nicht auftreten, würde in MyClass stehen

 

void Awake ()

{

myClass = this;

}

 

Denn Awake wird ja in jedenfall vor Start aufgerufen, hier wäre man also sicher, dass die Variable initialisiert wäre, noch bevor man in der anderen Classe in der Start auf diese zugreift.

 

Ums kurz Zusagen, ich verwende also für verschiedene Dinge die verschiedenen Initialisierungsfunktionen.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Okay, ich glaube ich hab verstanden was du meinst ^^

Ja gut, aber wenn man die Script Execution Order setzt sollte das ja auch trotzdem funktionieren oder?

 

Außerdem funktioniert das nur wenn nur eine Abhängigkeit zwischen 2 Scripts da ist oder?

Angenommen ich hab 4 Scripts die so voneinander abhängen wie du es beschrieben hast (keine Ahnung in welchem Anwendungsfall das so sein sollte aber man weiß ja nie ^^).

Script A braucht Daten von Script B, B von C und C von D

Also muss die Reihenfolge exakt sein

 

D -> C -> B -> A

 

Die Reihenfolge in der die Awakes der Objekte ausgeführt werden ist aber doch ziemlich willkürlich da es davon abhängt wann was geladen wurde und wenn aber jetzt B vor C geladen wird, wird ja auch die Awake zuerst bei B und dann erst bei C aufgerufen richtig?

Dann hab ich aber genau dein oben beschriebenes Problem das du versuchst mit der Awake() zu umgehen.

Also braucht man sowieso wieder eine Script Execution Order und ich kann auch einfach die Start() benutzen? ^^

Link zu diesem Kommentar
Auf anderen Seiten teilen

Viele Wege führen nach Rom. Natürlich kannst du auch alles über die Execution Order und Start steuern. Aber du kannst eben bestimmmte Sachen leichter über Awake machen, ohne noch extra bei jedem Script nachzustochern in welcher Reihenfolge die Geschichte abgearbeitet wird. Denn du weisst Awake kommt vor Start.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Dass man mehr als eine Abhängigkeit in der Kette hat ist ziemlich selten. Meistens hängt eine Aktion (wenn überhaupt) nämlich davon ab, dass eine gewisse Information bereits vorhanden ist. Z.B. eine Referenz auf eine Komponente. Du hast so gut wie nie, dass ein Objekt gefärbt wird, NACHDEM von einem anderen Objekt die Position geändert wurde - weil beides im selben Schritt passiert.

Stattdessen benötigt das Objekt z.B. den Renderer des anderen Objektes, um sich die Farbe zu kopieren.

 

Wenn nun ein Skript etwas raus sucht, und eine anderes davon abhängig etwas raus sucht, und ein drittes DAVON abhängig etwas macht, dann reicht Awake+Start wirklich nicht mehr. Aber wenn du so eine Kette von voneinander abhängigen Variablenwerrten hast, dann solltest du sowieso mal drüber nachdenken, was da los ist :)

Link zu diesem Kommentar
Auf anderen Seiten teilen

Also wenn ich das richtig in erinnerung habe wird awake angerufen wenn alles initialisiert wurde, und start wenn das script enabled wurde, könnte also auch erst später während runtime sein!

 

fällt mir zwar jetzt kein fallbeispiel zu ein, aber damit haste schonmal nen großen unterschied.

 

ansonsten sagt unity noch:

Each GameObject's Awake is called in a random order between objects. Because of this, you should use Awake to set up references between scripts, and use Start to pass any information back and forth. Awake is always called before any Start functions. This allows you to order initialization of scripts.

 

wobei ich jetzt den unterschied nicht verstehe zwischen referenzen und die informationen, evtl kann sascha das mal übersetzen :D

Link zu diesem Kommentar
Auf anderen Seiten teilen

Wenn ich mal kurz darf. :)

 

Vieles ist schon richtig, aber einiges wurde noch außer Acht gelassen.

 

Klar ist, dass Awake() vor dem Start() ausgeführt wird. Das ist so in jedem Script und das ist so, wenn ganz viele Scripte gleichzeitig beim Spielstart schon in der Szene sind. Wobei von allen Scripten dann erst einmal Awake() ausgeführt wird und danach die Start().

 

In der ExecutionOrder kann man zusätzlich noch sagen, welches Script denn vor einem anderen Script ablaufen soll. Das bezieht sich dann auf die Reihenfolge in der alles Awakes und Starts abgefahren werden. Z.B. würde vom Script "Eigenschaften" zuerst die Awake abgefahren um eine Eigenschaft in eine statische Variable zu schreiben. Dann erst würde das Script " Addon" auf Grund der Eigenschaften in der Awake darauf reagieren.

Die Execution Order nimmt man aber eher für die anderen Funktionen wie z.B. Update() Wo es wirklich zu Problemen kommen könnte, wenn ein gewisses Script vor einem anderen ausgeführt würde, weil sie sich evtl. gegenseitig Werte überschreiben.

 

Normalerweise braucht man die ExecutionOrder echt nur selten. Beim Plugin NGUI wird das genutzt, weil gewisse GUI Dinge vor dem normalen Code kommen müssen!

 

Es gibt sie nur, weil es in Unity Zufall ist, welches Script zuerst seine Funktion abarbeitet.

 

Jetzt aber nochmal zurück zu Awake und Start.

 

Wenn man jetzt zum Beispiel nur nach einem Objekt suchen will welches nur in diesem Script von Bedeutung ist, kann man das in Awake oder der Start machen. Ist total egal, denn es muss nur vor dem Update passieren.

Wenn mehrere Scripte gleichzeitig starten, dann ist schon wichtig, was zuerst gemacht werden soll. Wenn z.B. jedes Script sich ersteinmal in einem Array bekannt machen soll, und danach dann dieses Array auslesen will um zu sehen, welche Scripte denn noch so da sind, muss man das Schreiben ins Array in der Awake machen und das Auslesen dann in der Start. Es macht keinen Sinn, wenn ein Script das Auslesen schon in der Awake macht, wo möglicherweise sich noch gar nicht alle Scripte ins Array eingetragen haben.

 

Und noch eine winzige Kleinigkeit, die große Bedeutung hat:

Wenn ein Objekt in einer Szene ist, dessen Script aber deaktiviert ist, wenn die Szene startet, so wird Awake trotzdem ausgeführt!

Aber nur Awake! Start wird erst dann ausgeführt, wenn das Script aktiviert wird.

Das Objekt kann sich also über die Awake schon einmal bekannt machen, ohne das weitere Funktionen des Objektes ausgeführt werden. Und erst wenn das Script aktiviert wird, würde für dieses Script das Leben mit der Start() beginnen.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Archiviert

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

×
×
  • Neu erstellen...