Da viele Benutzer mit dem NullReferenceException: Object reference not set to an instance of an object
Fehler in Unity konfrontiert sind , hielt ich es für eine gute Idee, aus mehreren Quellen einige Erklärungen und Möglichkeiten zur Behebung dieses Fehlers zu sammeln.
Symptome
Ich erhalte den folgenden Fehler in meiner Konsole. Was bedeutet das und wie behebe ich ihn?
NullReferenceException: Objektreferenz nicht auf eine Instanz eines Objekts festgelegt
unity
exceptions
Hellium
quelle
quelle
Antworten:
Werttyp vs Referenztyp
In vielen Programmiersprachen haben Variablen einen sogenannten "Datentyp". Die beiden primären Datentypen sind Werttypen (int, float, bool, char, struct, ...) und Referenztyp (Instanz von Klassen). Während Werttypen den Wert selbst enthalten , enthalten Referenzen eine Speicheradresse, die auf einen Teil des Speichers verweist, der eine Reihe von Werten enthält (ähnlich wie C / C ++).
Beispielsweise
Vector3
handelt es sich um einen Werttyp (eine Struktur, die die Koordinaten und einige Funktionen enthält), während an Ihr GameObject angehängte Komponenten (einschließlich Ihrer benutzerdefinierten Skripts, von denen geerbt wirdMonoBehaviour
) Referenztypen sind.Wann kann ich eine NullReferenceException haben?
NullReferenceException
werden ausgelöst, wenn Sie versuchen, auf eine Referenzvariable zuzugreifen, die auf kein Objekt verweist. Daher ist sie null (die Speicheradresse zeigt auf 0).Einige gemeinsame Orte
NullReferenceException
werden angesprochen:Bearbeiten eines GameObject / einer Komponente, die im Inspektor nicht angegeben wurde
Rufen Sie eine Komponente ab, die nicht an das GameObject angehängt ist, und versuchen Sie dann, sie zu manipulieren:
Zugriff auf ein GameObject, das nicht existiert:
Hinweis: Seien Sie vorsichtig,
GameObject.Find
,GameObject.FindWithTag
,GameObject.FindObjectOfType
nur zurückkehren , die Gameobjects sind aktiviert in der Hierarchie , wenn die Funktion aufgerufen wird.Der Versuch, das Ergebnis eines zurückkehrenden Getters zu verwenden
null
:Zugriff auf ein Element eines nicht initialisierten Arrays
Weniger verbreitet, aber ärgerlich, wenn Sie nichts über C # -Delegierte wissen:
Wie repariert man ?
Wenn Sie die vorherigen Absätze verstanden haben, wissen Sie, wie Sie den Fehler beheben können: Stellen Sie sicher, dass Ihre Variable auf eine Instanz einer Klasse verweist (oder auf diese zeigt) (oder mindestens eine Funktion für Delegaten enthält).
Leichter gesagt als getan? Ja, in der Tat. Hier sind einige Tipps, um das Problem zu vermeiden und zu identifizieren .
Der "schmutzige" Weg: Die Try & Catch-Methode:
Der "sauberere" Weg (IMHO): Der Scheck
Wenn Sie auf einen Fehler stoßen, den Sie nicht lösen können, ist es immer eine gute Idee, die Ursache des Problems zu finden. Wenn Sie "faul" sind (oder wenn das Problem leicht gelöst werden kann), verwenden Sie
Debug.Log
zeigen Sie auf der Konsole Informationen an, anhand derer Sie ermitteln können, was das Problem verursachen könnte. Eine komplexere Möglichkeit besteht darin, die Haltepunkte und den Debugger Ihrer IDE zu verwenden.Die Verwendung
Debug.Log
ist sehr nützlich, um beispielsweise zu bestimmen, welche Funktion zuerst aufgerufen wird. Insbesondere, wenn Sie eine Funktion haben, die für die Initialisierung von Feldern verantwortlich ist. Aber vergessen Sie nicht, diese zu entfernenDebug.Log
, um ein Überladen Ihrer Konsole (und aus Leistungsgründen) zu vermeiden.Ein weiterer Rat, zögern Sie nicht, Ihre Funktionsaufrufe zu "kürzen" und hinzuzufügen
Debug.Log
, um einige Überprüfungen durchzuführen.Anstatt :
Überprüfen Sie hiermit, ob alle Referenzen festgelegt sind:
Noch besser :
Quellen:
quelle
try/catch
. Der Fehler sagt viel über das Problem aus, das Sie dort haben, und bevor Anfänger überall Nullprüfungen durchführen, liegt das Hauptproblem im Inspektor, da Sie vergessen, auf ein Objekt zu verweisen (Objekt auf das Skript ziehen). Ich habe viel Code mittry/catch
und Nullprüfungen an Stellen gesehen, an denen dies völlig unnötig ist. Das Debuggen und Arbeiten mit einem solchen Code ist "ein Schmerz im A **". Anfänger lernen die Anwendungsfälle dieser Prüfungen kennen und verwenden sie erst dann.else
. Ein zu habenNullReferenceException
ist nicht immer selbsterklärend, während esNo Rigidbody component attached to the gameObject
direkt erklärt, was falsch ist. Ich bin damit einverstanden, dass nur das Fehlen derif( obj != null )
Nachricht das Problem "verbirgt" und Sie ein funktionierendes Projekt haben können, aber nicht das tun, was Sie erwarten würden, ohne zu wissen warum.Wir können zwar einfach eine Überprüfung durchführen, um sicherzustellen, dass wir nicht versuchen, auf eine Nullreferenz zuzugreifen, dies ist jedoch nicht immer eine geeignete Lösung. In der Unity-Programmierung kann unser Problem häufig auf die Tatsache zurückzuführen sein, dass die Referenz nicht null sein sollte. In einigen Situationen kann das einfache Ignorieren von Nullreferenzen unseren Code beschädigen.
Dies könnte beispielsweise ein Verweis auf unseren Eingangscontroller sein. Es ist großartig, dass das Spiel aufgrund der Nullreferenzausnahme nicht abstürzt, aber wir müssen herausfinden, warum es keinen Eingabecontroller gibt, und dieses Problem beheben . Ohne sie haben wir ein Spiel, das möglicherweise nicht abstürzt, aber auch keine Eingaben entgegennimmt.
Im Folgenden werde ich mögliche Gründe und Lösungen auflisten, auf die ich in anderen Fragen stoße.
Versuchen Sie, auf eine "Manager" -Klasse zuzugreifen?
Wenn Sie versuchen, auf eine Klasse zuzugreifen, die als "Manager" fungiert (dh eine Klasse, auf der immer nur eine Instanz gleichzeitig ausgeführt werden sollte), ist es möglicherweise besser, den Singleton-Ansatz zu verwenden . Auf eine Singleton-Klasse kann idealerweise direkt von überall aus zugegriffen werden, indem ein
public static
Verweis auf sich selbst beibehalten wird. Auf diese Weise kann ein Singleton einen Verweis auf die aktive Instanz enthalten, auf den zugegriffen werden kann, ohne dass jedes Mal der eigentliche Verweis eingerichtet werden muss.Verweisen Sie auf die Instanz Ihres Objekts?
Es ist üblich, eine Referenz einfach als zu markieren
public
, damit wir die Referenz über den Inspektor auf die Instanz setzen können. Prüfen Sie immer , dass Sie haben den Verweis auf eine Instanz festgelegt, über den Inspektor, da es nicht ungewöhnlich ist , diesen Schritt zu verpassen.Instanziieren Sie Ihre Instanz?
Wenn wir unser Objekt im Code einrichten, ist es wichtig sicherzustellen, dass wir das Objekt instanziieren . Dies kann mit dem
new
Schlüsselwort und den Konstruktormethoden durchgeführt werden. Betrachten Sie beispielsweise Folgendes:Wir haben einen Verweis auf a erstellt
GameObject
, der jedoch auf nichts verweist. Der Zugriff auf diese Referenz können wie in einer Folge NULL - Verweis Ausnahme . Bevor wir auf unsereGameObject
Instanz verweisen , können wir eine Standardkonstruktormethode wie folgt aufrufen:Das Unity-Lernprogramm für Klassen erläutert die Vorgehensweise beim Erstellen und Verwenden von Konstruktoren.
Verwenden Sie die
GetComponent<t>()
Methode unter der Annahme, dass die Komponente vorhanden ist?Stellen Sie zunächst sicher, dass wir immer anrufen
GetComponent<t>()
bevor wir Methoden von der Komponenteninstanz aufrufen.Aus Gründen, die es nicht wert sind, untersucht zu werden, können wir davon ausgehen, dass unser lokales Spielobjekt eine bestimmte Komponente enthält, und versuchen, mit darauf zuzugreifen
GetComponent<t>()
. Wenn das lokale Spielobjekt diese bestimmte Komponente nicht enthält, geben wir einennull
Wert zurück.Sie können leicht überprüfen, ob der Rückgabewert ist
null
, bevor Sie darauf zugreifen. Wenn Sie Ihr Spiel Objekt jedoch sollte die erforderliche Komponente hat, kann es besser sein , um sicherzustellen , dass es mindestens eine hat Standard - Version dieser Komponente. Wir können einMonoBehaviour
als kennzeichnen,[RequireComponent(typeof(t))]
um sicherzustellen, dass wir immer diese Art von Komponente haben.Hier ist ein Beispiel für ein
MonoBehaviour
für ein Spielobjekt, das immer ein enthalten sollteRigidbody
. Wenn das Skript einem Spielobjekt hinzugefügt wird, das kein enthältRigidbody
, wird ein StandardRigidbody
erstellt.Haben Sie versucht, Ihr Projekt neu aufzubauen?
In einigen Fällen kann Unity Probleme verursachen, wenn versucht wird, auf eine zwischengespeicherte Version eines Spielobjekts zu verweisen . Versuchen Sie im Einklang mit der uralten Lösung "Aus- und wieder einschalten", Ihren Bibliotheksordner zu löschen und Unity erneut zu öffnen. Unity wird gezwungen sein, Ihr Projekt neu aufzubauen. Dies kann einige sehr eigenartige Fälle dieses Problems lösen und sollte auf Probleme hinweisen, die in einem endgültigen Build nicht auftreten würden.
quelle
Ich sehe, dass es eine akzeptierte Antwort gibt. Es gibt jedoch eine bessere Antwort oder einen besseren Vorschlag für die Handhabung
NullReferenceException
. Wenn Sie die Programmierung in Java-Sprache wie ich beziehen können, können Sie verhindern, dass ein Nullfehler gesendet wird, indem Sie dietry-catch
Blocks . Probieren Sie es aus! ;-);Wenn Sie in C # verwenden, überprüfen Sie, ob Sie
using System;
oben in Ihrer Skriptdatei haben. Wenn nicht, fügen Sie es hinzu. Jetzt können Sie alle Arten vonException
Klassen verwenden, während Sie versuchen, eine Codezeile abzufangen.Wenn Sie UnityScript verwenden, verwenden Sie
import System;
Hier ist ein Beispiel:
Denken Sie auch daran, können Sie auch andere Ausnahmen wie fangen
MissingReferenceException
,MissingComponentException
,IndexOutOfRangeException
, oder jede andere Ausnahmeklassen, solange Sie umfassenusing System
in Ihrem Skript.Das ist alles.
quelle