A NullReferenceException
happens when you try to access a reference variable that isn’t referencing any object. If a reference variable isn’t referencing an object, then it’ll be treated as null
. The run-time will tell you that you are trying to access an object, when the variable is null
by issuing a NullReferenceException
.
Reference variables in c# and JavaScript are similar in concept to pointers in C and C++. Reference types default to null
to indicate that they are not referencing any object. Hence, if you try and access the object that is being referenced and there isn’t one, you will get a NullReferenceException
.
When you get a NullReferenceException
in your code it means that you have forgotten to set a variable before using it. The error message will look something like:
NullReferenceException: Object reference not set to an instance of an object
at Example.Start () [0x0000b] in /Unity/projects/nre/Assets/Example.cs:10
This error message says that a NullReferenceException
happened on line 10 of the script file Example.cs
. Also, the message says that the exception happened inside the Start()
function. This makes the Null Reference Exception easy to find and fix. In this example, the code is:
//c# example
using UnityEngine;
using System.Collections;
public class Example : MonoBehaviour {
// Use this for initialization
void Start () {
__GameObject__The fundamental object in Unity scenes, which can represent characters, props, scenery, cameras, waypoints, and more. A GameObject's functionality is defined by the Components attached to it. [More info](class-GameObject.html)<span class="tooltipGlossaryLink">See in [Glossary](Glossary.html#GameObject)</span> go = GameObject.Find("wibble");
Debug.Log(go.name);
}
}
The code simply looks for a game object called “wibble”. In this example there is no game object with that name, so the Find()
function returns null
. On the next line (line 9) we use the go
variable and try and print out the name of the game object it references. Because we are accessing a game object that doesn’t exist the run-time gives us a NullReferenceException
Null Checks
Although it can be frustrating when this happens it just means the script needs to be more careful. The solution in this simple example is to change the code like this:
using UnityEngine;
using System.Collections;
public class Example : MonoBehaviour {
void Start () {
GameObject go = GameObject.Find("wibble");
if (go) {
Debug.Log(go.name);
} else {
Debug.Log("No game object called wibble found");
}
}
}
Now, before we try and do anything with the go
variable, we check to see that it is not null
. If it is null
, then we display a message.
Try/Catch Blocks
Another cause for NullReferenceException
is to use a variable that should be initialised in the InspectorA Unity window that displays information about the currently selected GameObject, asset or project settings, allowing you to inspect and edit the values. More info
See in Glossary. If you forget to do this, then the variable will be null
. A different way to deal with NullReferenceException
is to use try/catch block. For example, this code:
using UnityEngine;
using System;
using System.Collections;
public class Example2 : MonoBehaviour {
public Light myLight; // set in the inspector
void Start () {
try {
myLight.color = Color.yellow;
}
catch (NullReferenceException ex) {
Debug.Log("myLight was not set in the inspector");
}
}
}
In this code example, the variable called myLight
is a Light
which should be set in the Inspector window. If this variable is not set, then it will default to null
. Attempting to change the color of the light in the try
block causes a NullReferenceException
which is picked up by the catch
block. The catch
block displays a message which might be more helpful to artists and game designers, and reminds them to set the light in the inspector.
Summary
-
NullReferenceException
happens when your script code tries to use a variable which isn’t set (referencing) and object. - The error message that appears tells you a great deal about where in the code the problem happens.
-
NullReferenceException
can be avoided by writing code that checks fornull
before accessing an object, or uses try/catch blocks.
NullReferenceException
возникает, когда вы пытаетесь получить доступ к ссылочной переменной, которая не ссылается на какой-либо объект. Если ссылочная переменная не ссылается на объект, она будет рассматриваться как null
. Время выполнения сообщит вам, что вы пытаетесь получить доступ к объекту, когда переменная имеет значение null
, создав исключение NullReferenceException
.
Ссылочные переменные в C# и JavaScript по своей концепции аналогичны указателям в C и C++. Типы ссылок по умолчанию имеют значение null
, чтобы указать, что они не ссылаются на какой-либо объект. Следовательно, если вы попытаетесь получить доступ к объекту, на который ссылаются, а его нет, вы получите NullReferenceException
.
Когда вы получаете NullReferenceException
в своем коде, это означает, что вы забыли установить переменную перед ее использованием. Сообщение об ошибке будет выглядеть примерно так:
NullReferenceException: Object reference not set to an instance of an object
at Example.Start () [0x0000b] in /Unity/projects/nre/Assets/Example.cs:10
В этом сообщении об ошибке говорится, что NullReferenceException
произошло в строке 10 файла сценария Example.cs
. Кроме того, в сообщении говорится, что исключение произошло внутри функции Start()
. Это упрощает поиск и исправление исключения нулевой ссылки. В этом примере код такой:
//c# example
using UnityEngine;
using System.Collections;
public class Example : MonoBehaviour {
// Use this for initialization
void Start () {
__GameObject__The fundamental object in Unity scenes, which can represent characters, props, scenery, cameras, waypoints, and more. A GameObject's functionality is defined by the Components attached to it. [More info](class-GameObject)See in [Glossary](Glossary#GameObject) go = GameObject.Find("wibble");
Debug.Log(go.name);
}
}
Код просто ищет игровой объект под названием «wibble». В этом примере нет игрового объекта с таким именем, поэтому функция Find()
возвращает null
. В следующей строке (строка 9) мы используем переменную go
и пытаемся вывести имя игрового объекта, на который она ссылается. Поскольку мы обращаемся к несуществующему игровому объекту, среда выполнения выдает нам NullReferenceException
Нулевые проверки
Хотя это может расстраивать, когда это происходит, это просто означает, что сценарий должен быть более осторожным. Решение в этом простом примере состоит в том, чтобы изменить код следующим образом:
using UnityEngine;
using System.Collections;
public class Example : MonoBehaviour {
void Start () {
GameObject go = GameObject.Find("wibble");
if (go) {
Debug.Log(go.name);
} else {
Debug.Log("No game object called wibble found");
}
}
}
Теперь, прежде чем пытаться что-то делать с переменной go
, мы проверяем, не является ли она null
. Если это null
, мы показываем сообщение.
Попробовать/перехватить блоки
Другой причиной NullReferenceException
является использование переменной, которая должна быть инициализирована в ИнспектореОкно Unity, в котором отображается информация о текущем выбранном игровом объекте, активе или настройках проекта, что позволяет просматривать и редактировать значения. Дополнительная информация
См. в Словарь. Если вы забудете это сделать, переменная будет иметь значение null
. Другой способ справиться с NullReferenceException
— использовать блок try/catch. Например, этот код:
using UnityEngine;
using System;
using System.Collections;
public class Example2 : MonoBehaviour {
public Light myLight; // set in the inspector
void Start () {
try {
myLight.color = Color.yellow;
}
catch (NullReferenceException ex) {
Debug.Log("myLight was not set in the inspector");
}
}
}
В этом примере кода переменная с именем myLight
— это Light
, которую следует установить в окне инспектора. Если эта переменная не задана, по умолчанию она будет иметь значение null
. Попытка изменить цвет света в блоке try
вызывает NullReferenceException
, которое подхватывается блоком catch
. Блок catch
отображает сообщение, которое может быть более полезным для художников и геймдизайнеров, и напоминает им о необходимости установить свет в инспекторе.
Обзор
-
NullReferenceException
возникает, когда ваш код скрипта пытается использовать переменную, которая не установлена (ссылка) и объект. - Отображаемое сообщение об ошибке многое говорит о том, в каком месте кода возникает проблема.
NullReferenceException
можно избежать, написав код, который проверяетnull
перед доступом к объекту или использует блоки try/catch.
Value type vs Reference type
In many programming languages, variables have what is called a «data type». The two primary data types are value types (int, float, bool, char, struct, …) and reference type (instance of classes). While value types contains the value itself, references contains a memory address pointing to a portion of memory allocated to contain a set of values (similar to C/C++).
For example, Vector3
is a value type (a struct containing the coordinates and some functions) while components attached to your GameObject (including your custom scripts inheriting from MonoBehaviour
) are reference type.
When can I have a NullReferenceException?
NullReferenceException
are thrown when you try to access a reference variable that isn’t referencing any object, hence it is null (memory address is pointing to 0).
Some common places a NullReferenceException
will be raised:
Manipulating a GameObject / Component that has not been specified in the inspector
// 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();
}
Retrieving a component that isn’t attached to the GameObject and then, trying to manipulate it:
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 ;
}
Accessing a GameObject that doesn’t exist:
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";
}
Note: Be carefull, GameObject.Find
, GameObject.FindWithTag
, GameObject.FindObjectOfType
only return gameObjects that are enabled in the hierarchy when the function is called.
Trying to use the result of a getter that’s returning 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.
Accessing an element of a non-initialized array
private GameObject[] myObjects ; // Uninitialized array
private void Start()
{
for( int i = 0 ; i < myObjects.Length ; ++i )
Debug.Log( myObjects[i].name ) ;
}
Less common, but annoying if you don’t know it about C# delegates:
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) ;
}
How to fix ?
If you have understood the previous paragraphes, you know how to fix the error: make sure your variable is referencing (pointing to) an instance of a class (or containing at least one function for delegates).
Easier said than done? Yes, indeed. Here are some tips to avoid and identify the problem.
The «dirty» way : The try & catch method :
Collider collider = gameObject.GetComponent<Collider>();
try
{
collider.enabled = false ;
}
catch (System.NullReferenceException exception) {
Debug.LogError("Oops, there is no collider attached", this) ;
}
The «cleaner» way (IMHO) : The check
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) ;
}
When facing an error you can’t solve, it’s always a good idea to find the cause of the problem. If you are «lazy» (or if the problem can be solved easily), use Debug.Log
to show on the console information which will help you identify what could cause the problem. A more complex way is to use the Breakpoints and the Debugger of your IDE.
Using Debug.Log
is quite useful to determine which function is called first for example. Especially if you have a function responsible for initializing fields. But don’t forget to remove those Debug.Log
to avoid cluttering your console (and for performance reasons).
Another advice, don’t hesitate to «cut» your function calls and add Debug.Log
to make some checks.
Instead of :
GameObject.Find("MyObject").GetComponent<MySuperComponent>().value = "foo" ;
Do this to check if every references are set :
GameObject myObject = GameObject.Find("MyObject") ;
Debug.Log( myObject ) ;
MySuperComponent superComponent = myObject.GetComponent<MySuperComponent>() ;
Debug.Log( superComponent ) ;
superComponent.value = "foo" ;
Even better :
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 ) ;
}
Sources:
- http://answers.unity3d.com/questions/47830/what-is-a-null-reference-exception-in-unity.html
- https://stackoverflow.com/questions/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
Explanation
In C# generally, this is caused by referencing a field that hasn’t been initialized. For example, if you have a field public List<GameObject> items
and you later call items.Add(foo)
without first doing items = new List<GameObject>()
, then you are trying to add an item to a list that doesn’t exist.
However, in Unity specifically, this is most frequently caused by forgetting to set a reference in the inspector. When you create a new component and add a field public Transform destination
, then you most likely are intending to assign a prefab in the inspector. If you forget, you’re trying to reference something that doesn’t exist.
Solutions
If you double-click on the error message in the console window, Unity will (with a few exceptions) highlight the GameObject in the hierarchy that threw the error, and open your code editor and highlight the line of the script where the error occurred.
-
If you are using any of the
Find
-like methods to get the GameObject, be sure that the GameObject is active, otherwiseFind
-like methods will return null or may return the wrong GameObject. If you need the GameObject to be inactive when it is found, you need to use a different way of getting a reference to the GameObject than using aFind
-like method to find the GameObject directly, such as having the component register with a Manager-type class. -
Looking at the GameObject, make sure you’ve assigned everything in the inspector that should be assigned.
-
If everything has been assigned, run the game with the GameObject that threw the error selected. It’s possible that you have something in
Awake()
orStart()
that’s negating the reference, and you’ll see the inspector switch toNone
.
-
Pay attention to the return types of methods you use to modify objects. For example, if you call
GetComponent()
or anything similar on an object and the component is not found, it will not throw an error. It will just return null. This can easily be handled with a line like:if(thing == null) //log an error, or do something to fix the reference else //do what you wanted to do
That should cover the most frequent Unity-specific causes. If that still isn’t fixing your issue, Unity’s own page on NullReferenceException, and for C# generally, there’s a more in-depth explanation of NullReferenceException in this answer.
An error involving a NullReferenceException
is something that new developers often encounter when working on projects in Unity. These errors occur when attempting to access object variables, or members of object variables, when the variable itself is null.
Although the cause is simple, NullReferenceException
errors can present themselves in many different ways. As a result, fixing them isn’t always as straightforward as following a standard series of steps. In this article, we will explore the various ways that a NullReferenceException
can occur in Unity, as well as how to handle these various situations.
- Why is it a
NullReferenceException
? - How do they happen (and how do we fix them)?
- Trying to access a method or property (of a null object)
- Accessing a destroyed object
- Using an unassigned public variable
- Not every variable can have a null reference
- Conclusion
1. Why is it a NullReferenceException
?
A NullReferenceException
is an error that happens when your code tries to access an object variable (also known as a reference variable) that doesn’t exist (i.e. the value of the variable is null). Do you see where the name comes from now?
Object variables are called reference variables because the data for the object is stored in a separate address from the variable itself in memory (i.e. RAM). Instead of containing the data, the object variable will instead contain the reference address of the actual object. In layman terms, this means that the variable points to the object instead of storing it, like how a mailing address points to a house.
Hence, it is possible for different variables to point to the same object, such that modifying one variable will affect the value of another. Below is a simple example that illustrates this:
GameObject a = new GameObject(); GameObject b = a; b.name = "Awesome name"; print(a.name);
Interested to find out more about reference variables? You can check out our article about reference and value types in programming. This is a concept that is not exclusive to C# or Unity programming, so you will see it a lot when you work on other programming languages as well.
2. How do they happen (and how do we fix them)?
In a nutshell, whenever you see a NullReferenceException
, this means that some object variable in your code is null (i.e. empty) for some reason. Most commonly, you will find them in situations where you are…
a. Trying to access a method or property (of a null object)
Take the following example. It is a piece of code that can be attached to a GameObject to make it behave like a projectile, making it move rightwards the moment it spawns.
using UnityEngine; public class Projectile : MonoBehaviour { Rigidbody2D rb; public float speed = 10f; void Update() { rb.velocity = transform.right * speed; } }
This is how a GameObject with the script attached will behave:
If you attach it the script to any GameObject in your Scene, however, you will get a NullReferenceException
in the highlighted line above. This is because the variable rb
has never been assigned a value, so running rb.velocity
is the same as running null.velocity
.
To rectify this, we will have to ensure that rb
is assigned before we try to access its properties. A simple way to do this for our script is to add the following:
using UnityEngine; public class Projectile : MonoBehaviour { Rigidbody2D rb; public float speed = 10f; void Start() { rb = GetComponent<Rigidbody2D>(); } void Update() { rb.velocity = transform.right * speed; } }
Be aware that your GameObject will need to have a Rigidbody2D
component for this to work. Otherwise, GetComponent<Rigidbody2D>()
will return null and you will get a null reference error anyway.
Rigidbody2D
component is required for this to work.Some additional notes:
NullReferenceException
errors can occur even if you try to access methods of null objects. For example, usingrb.AddForce(transform.right * speed)
in the above example will give the same error.- When accessing properties within properties, it is possible for any object in the chain of properties to be null. For example,
Rigidbody2D
objects have asharedMaterial
property, which may or may not be null. Hence, in a line likerb.sharedMaterial.bounciness
, it is possible for eitherrb
orsharedMaterial
to be null, and either one being null will cause aNullReferenceException
.
Article continues after the advertisement:
b. Accessing a destroyed object
Sometimes, it is possible for a NullReferenceException
to occur even if you properly assign your variables before you use them. Consider the following example:
using UnityEngine; public class Shooter : MonoBehaviour { public GameObject bulletPrefab; GameObject lastBullet; void Update() { if(Input.GetKeyDown(KeyCode.Space)) { lastBullet = Instantiate(bulletPrefab, transform.position, transform.rotation); Destroy(lastBullet, 2); } if(Input.GetKeyDown(KeyCode.LeftControl)) { print(lastBullet.name); } } }
This is a script that can be attached to a GameObject so that:
- Space causes it to shoot the projectiles we made earlier, save a reference to the projectile, and destroy the new projectile after 2 seconds.
- Ctrl causes it to print out the name of the last projectile we shot.
If you press Ctrl more than 2 seconds after shooting your last projectile, you will either get a NullReferenceException
or its closely-related cousin, a MissingReferenceException
.
This is because although lastBullet
points to an object, if the object it points to gets destroyed, then the lastBullet
variable will also become null.
If you want to prevent error messages from happening in such a case, you can add a check to see if an object variable is null before using it:
using UnityEngine; public class Shooter : MonoBehaviour { public GameObject bulletPrefab; GameObject lastBullet; void Update() { if(Input.GetKeyDown(KeyCode.Space)) { lastBullet = Instantiate(bulletPrefab, transform.position, transform.rotation); Destroy(lastBullet, 2); } if(Input.GetKeyDown(KeyCode.LeftControl) && lastBullet != null) { print(lastBullet.name); } } }
Article continues after the advertisement:
c. Using an unassigned public variable
Taking the example from (2) above, we can also get a closely-related cousin of the NullReferenceException
(called the UnassignedReferenceException
) if we try to fire a bullet with an unassigned bulletPrefab
variable.
To fix these errors, the solution is simple: Make sure you assign all the public variables you plan to use! If you would like a failsafe in case you forget to assign them, you can include a check to see if the object variable you want to use is null:
using UnityEngine; public class Shooter : MonoBehaviour { public GameObject bulletPrefab; GameObject lastBullet; void Update() { if(Input.GetKeyDown(KeyCode.Space) && bulletPrefab != null) { lastBullet = Instantiate(bulletPrefab, transform.position, transform.rotation); Destroy(lastBullet, 2); } if(Input.GetKeyDown(KeyCode.LeftControl) && lastBullet != null) { print(lastBullet.name); } } }
3. Not every variable can have a null reference
In Unity, primitives (such as int
, float
and bool
) and structs are value types, not reference types. This means that variables belonging to these 2 categories are not objects and do not hold references. Hence, they cannot cause NullReferenceException
errors.
For more information on what value types are, you can check out this article:
4. Conclusion
It’s important to note that variables of reference types need to be properly initialized and assigned valid object references to avoid NullReferenceException
(and related) errors. By implementing defensive coding practices, performing null checks, and ensuring that you assign variables, you can mitigate the risk of encountering these errors.
Did we miss any potential cause (or fix) for NullReferenceException
errors? Feel free to highlight it to us in the comments below.
Article continues after the advertisement: