Kojote Geschrieben 13. Juni 2017 Melden Share Geschrieben 13. Juni 2017 Grüße! Kleine peinliche Frage zu GameObject.Find. Ich habe folgende Variable: private ButtonAktualisierer kameraButtonOben; Im Awake, möchte ich gerne eine Verbindung zu dem Objekt bzw. zu einer seiner Komponenten herstellen, dem Script Buttonaktualisierer: kameraButtonOben = GameObject.Find("/Canvas/Kamera oben").GetComponent<ButtonAktualisierer>(); Problem ist nun folgendes: NullReferenceException: Object reference not set to an instance of an object Kamerasteuerung.Awake () (at Assets/Scripts/Kamerasteuerung.cs:44) Kann mir das jemand erklären? Wenn ich normal nach Objekten suche, findet er sie auch und alles gut. Will ich jedoch auf eine bestimmte Komponente zugreifen, wie dem Script ButtonAktualisierer, bekomm ich einen Fehler. Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Zer0Cool Geschrieben 13. Juni 2017 Melden Share Geschrieben 13. Juni 2017 Hol die erst die Objektreferenz und dann die Komponente, dann kannst du auch besser unterscheiden, was er nicht findet: GameObject m_kameraButtonOben = GameObject.Find("/Canvas/Kamera oben"); if (m_kameraButtonOben!=null) { ButtonAktualisierer m_buttonAktualisierer = m_kameraButtonOben.GetComponent<ButtonAktualisierer>(); if (m_buttonAktualisierer==null) Debug.LogError("Skript 'ButtonAktualisierer' nicht gefunden!"); } else { Debug.LogError("Objekt '/Canvas/Kamera oben' nicht gefunden!"); } Ich denke er findet bei dir das Objekt nicht, da evtl. der Pfad falsch ist oder es nicht aktiv ist. Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Kojote Geschrieben 13. Juni 2017 Autor Melden Share Geschrieben 13. Juni 2017 vor 43 Minuten schrieb Zer0Cool: Ich denke er findet bei dir das Objekt nicht, da evtl. der Pfad falsch ist oder es nicht aktiv ist. Würde es hierbei Probleme geben? Es ist der Fall, dass ich beim Start das Object deaktiviert. Deswegen wird er es auch nicht finden. Kann man es finden, auch wenn es deaktiviert ist? EDIT: Was etwas blöd ist, merk ich gerade, ich lege einmal im Awake und Start die Verbindung zu dem Objekt fest. Wenn ich eine Ebene darüber, dass Objekt deaktiviere, findet er alle weiteren Objekte nicht mehr... Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Sascha Geschrieben 13. Juni 2017 Melden Share Geschrieben 13. Juni 2017 Und damit bist du an den Punkt gestoßen, wegen dem in Awake die Referenzen gesetzt werden und in Start die erste Logik passiert Alle Awakes sind vor allen Starts. Wenn du also in Awake GameObject.Find machst und in Start deaktivierst, sollte das funktionieren. Dann hast du "nur noch" das Problem, dass GameObject.Find trotzdem stark fehleranfällig ist. Mal vertippt, mal den Namen eines Objekts geändert und schon funktioniert dein Spiel nicht mehr. Leute sind immer genervt, wenn ich das sage, aber wenn's nach mir geht, sollte man in 99,9% aller Fälle von GameObject.Find komplett die Finger lassen. Es gibt immer alternative Wege. Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Kojote Geschrieben 13. Juni 2017 Autor Melden Share Geschrieben 13. Juni 2017 Ah, jetzt versteh ich endlich auch mal richitg den Unterschied zwischen Awake und Start, dank! Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
malzbie Geschrieben 13. Juni 2017 Melden Share Geschrieben 13. Juni 2017 Ich glaube das nicht. Denn da gibt es noch mehr, was Awake von Start unterscheidet. Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Helishcoffe Geschrieben 14. Juni 2017 Melden Share Geschrieben 14. Juni 2017 Soweit ich weiß wird Awake ja unmittelbar nach dem Instanziieren aufgerufen. Also bei der Methode Instantate wird z.B. direkt die Awake Methode aufgerufen. Start erst viel später. Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Torigas Geschrieben 14. Juni 2017 Melden Share Geschrieben 14. Juni 2017 Siehe hier https://docs.unity3d.com/Manual/ExecutionOrder.html Und falls Ihr mal was deterministisch machen wollt bzw. die Reihenfolge von einigen Scriptausführungen ändern wollt: https://docs.unity3d.com/Manual/class-ScriptExecution.html Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
malzbie Geschrieben 14. Juni 2017 Melden Share Geschrieben 14. Juni 2017 @Helishcoffe Ja, das bedeutet ja Awake. Ich könnte jetzt ne Menge schreiben, aber da ich mal ein Tut darüber gemacht hatte, hänge ich es mal an. Das erklärt so manches. Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Zer0Cool Geschrieben 14. Juni 2017 Melden Share Geschrieben 14. Juni 2017 Die Theorie ist das eine (Aufrufreihenfolge und Initialisierungszustände der Klassen und ihrer Instanzen zum Zeitpunkt von "Awake" und "Start"), ich habe allerdings eher "schlechte" Erfahrungen mit "Awake" gemacht und musste schon oft Initialisierungscode in die Startmethode hinein verschieben, um einen Fehler zu beheben, leider waren diese Fehler nur sehr schwer zu finden und oft auch nicht logisch zu erklären und auch Code von Assets die man kauft sind oft noch mit solchen Fehlern "gepflastert" (diese Fehler passieren dann eher "zufällig", da sie von der zufälligen Abarbeitung der Skripte abhängen) . Als "Daumenregel" würde ich sagen, das man nur einfachen Lowlevel-Initialisierungscode (Code mit wenigen Abhängigkeiten zu anderen Klassen oder Instanzen) in die Awake-Methode packen sollte, alle "höheren Funktionen" lieber in die Startmethode. Dabei zählen zu höheren Funktionen auch Unityeigene Systemfunktionen, bei denen Eigenschaften eingestellt werden. Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Sascha Geschrieben 14. Juni 2017 Melden Share Geschrieben 14. Juni 2017 Sag ich doch: Referenzen sammeln in Awake, Dinge ausführen/ändern in Start. Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Zer0Cool Geschrieben 14. Juni 2017 Melden Share Geschrieben 14. Juni 2017 Ja, das stimmt, aber auch mit Referenzen zu externen Objekten oder Komponenten in Awake wäre ich vorsichtig. Nur als Beispiel, oft werden Objekte in Awake- oder Start-Methoden aktiviert und wenn man in einer anderen Awake-Methode danach sucht, so wird das gesuchte Objekt ggf. nicht gefunden (hängt von der zufälligen Ausführungsreihenfolge ab), da Objekt.Find nur Objekte findet, die bereits aktiviert sind... Gleiches gilt auch für Komponenten, diese werden oftmals deaktiviert und wenn man in der Awakemethode versucht eine Liste mit Referenzen zu solchen Komponenten aufzubauen, so werden sie ggf. nicht gefunden (hier hängt es von der Suchmethode ab, es gibt eine Suchmethode, die auch deaktivierte Komponenten findet) Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Sascha Geschrieben 14. Juni 2017 Melden Share Geschrieben 14. Juni 2017 Klar - ist eher eine Faustregel. Es gibt halt ohne ein fünfjähriges, tiefgreifendes Studium der Informatik eigentlich keine Themen, bei denen man nicht bei jeder Aussage "prinzipiell" voranstellen und "aber da gibt es Ausnahmen" hinterherwerfen müsste Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Torigas Geschrieben 15. Juni 2017 Melden Share Geschrieben 15. Juni 2017 11 hours ago, Zer0Cool said: Ja, das stimmt, aber auch mit Referenzen zu externen Objekten oder Komponenten in Awake wäre ich vorsichtig. Nur als Beispiel, oft werden Objekte in Awake- oder Start-Methoden aktiviert und wenn man in einer anderen Awake-Methode danach sucht, so wird das gesuchte Objekt ggf. nicht gefunden (hängt von der zufälligen Ausführungsreihenfolge ab), da Objekt.Find nur Objekte findet, die bereits aktiviert sind... Gleiches gilt auch für Komponenten, diese werden oftmals deaktiviert und wenn man in der Awakemethode versucht eine Liste mit Referenzen zu solchen Komponenten aufzubauen, so werden sie ggf. nicht gefunden (hier hängt es von der Suchmethode ab, es gibt eine Suchmethode, die auch deaktivierte Komponenten findet) Deswegen kann man ja sagen, dass das eine Skript welches denn unbedingt nach anderen Objekten suchen muss, nach allen anderen ausgeführt wird. Siehe mein Post oben. Damit kann man die Initialisierung immernoch im Awake machen statt im Start, oder nicht? Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Zer0Cool Geschrieben 15. Juni 2017 Melden Share Geschrieben 15. Juni 2017 Leider sind es oft mehrere Skripte die nach externen Referenzen suchen. Ich würde mal sagen, bei Initialisierungen für das eigene Objekt (da man den Zustand ja kennt) ist Awake am besten geeignet, hier ist es dann im Endeffekt eine Art Standardkonstruktor für die MonoBehaviour-Klasse. Für Referenzen auf andere Objekte nur wenn man dessen Zustand (und die Auswirkungen auf einen Zugriff auf diese Objekte in der Awake-Methode) genau kennt. Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Sascha Geschrieben 15. Juni 2017 Melden Share Geschrieben 15. Juni 2017 Meine Methode, damit umzugehen, ist: Einfach keine transitiven Referenzen suchen. Wenn man in Awake bei Referenzen bleibt, statt Referenzen von referenzierten Objekten zu erfragen, ist man ziemlich safe. Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
KaBau Geschrieben 14. Januar 2018 Melden Share Geschrieben 14. Januar 2018 Hallo, Am 13.6.2017 um 16:12 schrieb Zer0Cool: Hol die erst die Objektreferenz und dann die Komponente, dann kannst du auch besser unterscheiden, was er nicht findet: Danke für diesen Satz. Folgendes klappte bei mir nicht (Wenn mein Player zerstört wurde und kurz darauf ein Prefab mittels Instantiate und dem unten stehenden Script erstellt wurde erhielt ich immer die Fehlermeldung: "NullReferenceException: Object reference not set to an instance of an object"): private Transform ply; public float moveSpeed = 0.1f; void Start() { ply = GameObject.Find("Player").transform; } void FixedUpdate() { if (ply) { transform.LookAt(ply); } transform.Translate(Vector3.forward * moveSpeed); } In der Fehlermeldung wurde auf die Zeile in der Start-Funktion verwiesen, in der ich den Player (oder besser gesagt seine Transform-Komponete) suchte. So hatte ich es in verschiedenen YouTube Tutorials gesehen. Aber wie oben geschrieben: es lief nicht richtig wenn der Player schon weg war. Folgendes klappte: private GameObject ply; public float moveSpeed = 0.1f; void Start() { ply = GameObject.Find("Player"); } void FixedUpdate() { if (ply) { transform.LookAt(ply.transform); } transform.Translate(Vector3.forward * moveSpeed); } Hier habe ich nun erst den Player gesucht und später in der FixedUpdate-Funktion die Transform-Komponente ausgewählt. Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
malzbie Geschrieben 14. Januar 2018 Melden Share Geschrieben 14. Januar 2018 Warum der erste Code bei dir nicht klappte, liegt daran, dass du ply zwar als Transform deklarierst, aber du ja nicht nach der Transformkomponente gesucht hast. Du hast da lediglich nach dem ganzen Gameobjekt gesucht und versucht das "Achtung" -kleingeschreibenes- transform zu verwenden. Das ist eine interne Referenz, aber nicht die Komponente! Das geht natürlich so nicht. Wenn du die Transformkomponente direkt referenzieren willst, dann musst du das so machen: ply=GameObject.Find("Player").GetComponent<Transform>(); Also erst das Gameobject finden und dann die Komponente des Gameobjects holen. In deinem 2ten Beispiel funktioniert das ohne die Komponente zu holen, weil du da ein GameObject suchst und der ply Variable übergibst. Das ist jetzt zwar nur ein GameObject, aber da ein GameObject nicht ohne Transform-Komponente existieren kann, wird automatisch von Unity eine Referenz gebildet und die kannst du jetzt über das kleingeschrieben transform erreichen. Unity macht das nur noch mit der Transformkomponente und dem GameObject welches dann gameObject heisst. In der Version 3 und evtl. sogar noch der Version 4, konntest du z.B. auch einen Rigidbody mit dem kleingeschriebenen rigidbody ansprechen und auch andere Dinge waren automatisiert. Das alles geht jetzt nicht mehr automatisch und du musst jetzt alle Komponenten, die du von einem GameObject ansprechen willst, selber referenzieren. So, wie ich es oben im Beispiel code geschrieben habe. Link zu diesem Kommentar Auf anderen Seiten teilen More sharing options...
Recommended Posts
Archiviert
Dieses Thema ist jetzt archiviert und für weitere Antworten gesperrt.