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 wird MonoBehaviour
) 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
// t is a reference to a Transform.
public Transform t ;
private void Awake()
{
// If you do not assign something to t
// (either from the Inspector or using GetComponent), t is null!
t.Translate();
}
Rufen Sie eine Komponente ab, die nicht an das GameObject angehängt ist, und versuchen Sie dann, sie zu manipulieren:
private void Awake ()
{
// Here, you try to get the Collider component attached to your gameobject
Collider collider = gameObject.GetComponent<Collider>();
// But, if you haven't any collider attached to your gameobject,
// GetComponent won't find it and will return null, and you will get the exception.
collider.enabled = false ;
}
Zugriff auf ein GameObject, das nicht existiert:
private void Start()
{
// Here, you try to get a gameobject in your scene
GameObject myGameObject = GameObject.Find("AGameObjectThatDoesntExist");
// If no object with the EXACT name "AGameObjectThatDoesntExist" exist in your scene,
// GameObject.Find will return null, and you will get the exception.
myGameObject.name = "NullReferenceException";
}
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
:
var fov = Camera.main.fieldOfView;
// main is null if no enabled cameras in the scene have the "MainCamera" tag.
var selection = EventSystem.current.firstSelectedGameObject;
// current is null if there's no active EventSystem in the scene.
var target = RenderTexture.active.width;
// active is null if the game is currently rendering straight to the window, not to a texture.
Zugriff auf ein Element eines nicht initialisierten Arrays
private GameObject[] myObjects ; // Uninitialized array
private void Start()
{
for( int i = 0 ; i < myObjects.Length ; ++i )
Debug.Log( myObjects[i].name ) ;
}
Weniger verbreitet, aber ärgerlich, wenn Sie nichts über C # -Delegierte wissen:
delegate double MathAction(double num);
// Regular method that matches signature:
static double Double(double input)
{
return input * 2;
}
private void Awake()
{
MathAction ma ;
// Because you haven't "assigned" any method to the delegate,
// you will have a NullReferenceException
ma(1) ;
ma = Double ;
// Here, the delegate "contains" the Double method and
// won't throw an exception
ma(1) ;
}
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:
Collider collider = gameObject.GetComponent<Collider>();
try
{
collider.enabled = false ;
}
catch (System.NullReferenceException exception) {
Debug.LogError("Oops, there is no collider attached", this) ;
}
Der "sauberere" Weg (IMHO): Der Scheck
Collider collider = gameObject.GetComponent<Collider>();
if(collider != null)
{
// You can safely manipulate the collider here
collider.enabled = false;
}
else
{
Debug.LogError("Oops, there is no collider attached", this) ;
}
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 SieDebug.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 :
GameObject.Find("MyObject").GetComponent<MySuperComponent>().value = "foo" ;
Überprüfen Sie hiermit, ob alle Referenzen festgelegt sind:
GameObject myObject = GameObject.Find("MyObject") ;
Debug.Log( myObject ) ;
MySuperComponent superComponent = myObject.GetComponent<MySuperComponent>() ;
Debug.Log( superComponent ) ;
superComponent.value = "foo" ;
Noch besser :
GameObject myObject = GameObject.Find("MyObject") ;
if( myObject != null )
{
MySuperComponent superComponent = myObject.GetComponent<MySuperComponent>() ;
if( superComponent != null )
{
superComponent.value = "foo" ;
}
else
{
Debug.Log("No SuperComponent found onMyObject!");
}
}
else
{
Debug.Log("Can't find MyObject!", this ) ;
}
Quellen:
- http://answers.unity3d.com/questions/47830/what-is-a-null-reference-exception-in-unity.html
- /programming/218384/what-is-a-nullpointerexception-and-how-do-i-fix-it/218510#218510
- https://support.unity3d.com/hc/en-us/articles/206369473-NullReferenceException
- https://unity3d.com/fr/learn/tutorials/topics/scripting/data-types