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.
If you don’t prefer reading and wish for more visual aid, check out our video guide here.
But if you prefer reading, scroll down to check the rest of the article.
In this article, here’s what we will be going through:
- Why is it a
NullReferenceException
? - How do they happen (and how do we fix them)?
- 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); // Gives "Awesome 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.
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
.
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; // Assigned in the Inspector. GameObject lastBullet; void Update() { // Spawn a bullet whenever you press space. if(Input.GetKeyDown(KeyCode.Space)) { lastBullet = Instantiate(bulletPrefab, transform.position, transform.rotation); Destroy(lastBullet, 2); // Destroy bullet after 2 seconds. } // Control will print the name of the lastBullet on the Console. 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; // Assigned in the Inspector. GameObject lastBullet; void Update() { // Spawn a bullet whenever you press space. if(Input.GetKeyDown(KeyCode.Space)) { lastBullet = Instantiate(bulletPrefab, transform.position, transform.rotation); Destroy(lastBullet, 2); // Destroy bullet after 2 seconds. } // Control will print the name of the lastBullet on the Console. if(Input.GetKeyDown(KeyCode.LeftControl) && lastBullet != null) { print(lastBullet.name); } } }
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; // Assigned in the Inspector. GameObject lastBullet; void Update() { // Spawn a bullet whenever you press space. if(Input.GetKeyDown(KeyCode.Space) && bulletPrefab != null) { lastBullet = Instantiate(bulletPrefab, transform.position, transform.rotation); Destroy(lastBullet, 2); // Destroy bullet after 2 seconds. } // Control will print the name of the lastBullet on the Console. 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.