Common Unity Errors and How To Fix Them - Part 1
-
Unity has a reputation for handing out surprises: the play-mode freeze just after a hot-reload, the sudden sea of pink materials, or the stack trace that politely reminds you your transform was null all along. Rather than letting those moments derail the rest of your sprint, this post rounds up four of the most common runtime offenders, and shows you exactly how to trigger, spot, and fix each one. We’ll cover:
To keep things concrete, we rebuilt every error inside a fresh HDRP sample project and wired up a no-frills SentryCube script so you can watch the problem (and the fix) play out in real time. Copy the code, skim for the snippet that matches your console, or just jump to the solution section, whatever gets you back to building faster.
NullReferenceException
in Unity: Object reference not set to an instance 1. How to fix
NullReferenceException
in Unity: Object reference not set to an instanceThe problem
We encounter this error when our script tries to use a reference that is null. Here’s what you’d typically see in your game’s console or log files:
UnassignedReferenceException: The variable target of SentryCube has not been assigned.
This commonly occurs when a GameObject
has a script that declares a public Transform target
field but doesn’t assign anything to it:
using UnityEngine;
public class SentryCube : MonoBehaviour
{
public Transform target; // left unassigned
void Start()
{
Debug.Log(target.position); // triggers the exception
}
}
When Start()
executes, target contains a null
value, so the call to position fails, and Unity halts and displays the UnassignedReferenceException
message above.
The solution
A NullReferenceException
error occurs when:
The variable points at nothing, because the
public Transform target
field was never populated in the Inspector.Another script destroys the referenced object (the
public Transform target
) during play and doesn’t clear the variable.The script execution order causes this script to run before the one that should have assigned the
public Transform target
field.
To fix this issue, we need to assign the reference or we need to guard against null
values.
First, let’s assign the reference:
Drag the correct Transform into the target slot in the Inspector window:
Inspector showing a missing target
Alternatively, set it in code before first use:
void Awake()
{
target = GameObject.FindWithTag("Player").transform;
}
Once you know the reference has been assigned, you should guard against null values when the object can disappear at runtime:
if (target == null)
{
Debug.LogWarning("SentryCube target missing, skipping movement logic");
return; // Skip the transform operations that would cause NullReferenceException
}
// Safe to use target.position, target.rotation, etc. here
While Unity’s Editor is forgiving with unassigned references and shows helpful warnings, in runtime builds, Unity typically swallows null reference
errors and logs them without line numbers. This leads to confusing behavior, like missing UI elements or objects that don’t appear as expected.
If the error results from an issue with the initialization order, ensure that any script responsible for filling the target runs first. There are two ways to do this:
Move the script’s assignment to
Awake()
.Adjust the Script Execution Order in your Project Settings.
Array index is out of range
errors in Unity? 2. What causes
Array index is out of range
errors in Unity?The problem
We see this error when our code attempts to access an array or list element that doesn’t exist:
IndexOutOfRangeException: Index was outside the bounds of the array
This typically happens when a GameObject
has a script that creates a fixed-size array but tries to access an index beyond its bounds:
using UnityEngine;
public class SentryCube : MonoBehaviour
{
int[] scores = new int[3]; // valid indices 0, 1, 2
void Start()
{
Debug.Log(scores[3]); // index 3 is illegal – triggers the exception
}
}
At runtime, scores[3]
is outside the valid range (which is 0
-2
), so the engine halts with the message above.
The solution
An IndexOutOfRangeException
error occurs when our variable holds fewer elements than the index we’re requesting. The array has a fixed size of three elements (with indices 0
, 1
, and 2
), but we’re trying to access index 3
, which doesn’t exist.
We can prevent the error from occurring by always checking the collection’s size before accessing an element, or by using a List<T>
that can grow as needed.
using UnityEngine;
using System.Collections.Generic;
public class SentryCube : MonoBehaviour
{
// Start with three values but List<T> can grow or shrink
[SerializeField] List<int> scores = new List<int>() { 10, 20, 30 };
void Start()
{
// Safe iteration
for (int i = 0; i < scores.Count; i++)
{
Debug.Log($"Score {i}: {scores[i]}");
}
// Safe single-index access
int index = 3; // this would have failed with an array
if (index >= 0 && index < scores.Count)
{
Debug.Log($"Requested score: {scores[index]}");
}
else
{
Debug.LogWarning($"Index {index} out of range – collection size is {scores.Count}");
}
}
}
When SentryCube runs with this code, it checks the index before accessing the list. If the index is out of range, it logs a warning instead of letting Unity swallow the error and create weird behavior like missing UI elements or unexpected gameplay issues.
Index Range Error
The key to avoiding this error is to use Count
(for lists) or Length
(for arrays) to ensure we only access valid indices. We should guard any direct index look-up with a simple range check, and prefer lists if the size can change.
MissingComponentException
3. How to fix a
MissingComponentException
The problem
We encounter the MissingComponentException
error when our script tries to use a Component
that doesn’t exist on the GameObject
. Let’s say we want to make our SentryCube hop upward when the game starts, so we write a script to apply an upward force:
MissingComponentException: There is no 'Rigidbody' attached to the "SentryCube" game object, but a script is trying to access it.
You probably need to add a Rigidbody to the game object "SentryCube". Or your script needs to check if the component is attached before using it.
This commonly happens when we have a GameObject with a script that attempts to get a Component and use it immediately, without checking whether it exists:
using UnityEngine;
public class SentryCube : MonoBehaviour
{
Rigidbody rb;
void Awake()
{
rb = GetComponent<Rigidbody>(); // returns null if Rigidbody is missing
}
void Start()
{
rb.AddForce(Vector3.up * 5f); // triggers the exception when rb is null
}
}
Because our SentryCube lacks a Rigidbody component, the call to AddForce hits a null reference, and Unity throws the error with the MissingComponentException message above.
SentryCube has no Rigidbody component
The solution
A MissingComponentException error occurs when:
The Component hasn’t been added to the GameObject.
The Component is removed at runtime.
The script assumes the Component will be there based on prefabs or variants.
As a result, we have several ways to fix this issue.
The simplest approach is to attach the required component manually in the Inspector.
Adding a Rigidbody component
Another option is to use the [RequireComponent] attribute, which automatically adds the dependency whenever our script is added to a GameObject:
using UnityEngine;
[RequireComponent(typeof(Rigidbody))] // Auto-creates component if missing
public class SentryCube : MonoBehaviour
{
Rigidbody rb;
void Awake()
{
rb = GetComponent<Rigidbody>();
}
void Start()
{
rb.AddForce(Vector3.up * 5f, ForceMode.Impulse);
}
}
However, [RequireComponent] can mask issues because it creates components with default values, which may not match your intended configuration. For example, the auto-created Rigidbody might have different mass, drag, or constraints than expected, causing unexpected physics behavior.
A more explicit approach is to programmatically check for the component and handle the missing case appropriately:
using UnityEngine;
public class SentryCube : MonoBehaviour
{
void Start()
{
Rigidbody rb = GetComponent<Rigidbody>();
if (rb == null)
{
Debug.LogError($"SentryCube on {gameObject.name} requires a Rigidbody component!");
return;
}
rb.AddForce(Vector3.up * 5f, ForceMode.Impulse);
}
}
This approach makes the dependency explicit and prevents silent failures in which the cube doesn’t move as expected due to incorrect default physics settings.
Your browser does not support the video tag.
4. How to resolve a MissingReferenceException when destroying objects
The problem
We encounter the MissingReferenceException error when our script holds a reference to a scene object that has already been destroyed:
UnassignedReferenceException: The variable projectile of SentryCube has not been assigned.
This typically happens when we have a script that destroys an object and then immediately tries to use it:
using UnityEngine;
public class SentryCube : MonoBehaviour
{
public GameObject projectile;
void Start()
{
DestroyImmediate(projectile); // object removed immediately
Debug.Log(projectile.name); // property access triggers the exception
}
}
The DestroyImmediate(projectile) function removes the object immediately. The reference in projectile still looks valid, but any call on it generates a MissingReferenceException error.
The solution
A MissingReferenceException error occurs when we try to access an object that no longer exists. Our code may still try to access the referenced GameObject after it has been destroyed, when:
A scene transition occurs, but we’re still holding references to objects from the previous scene.
Coroutines continue to run after their parent GameObject has been destroyed.
To fix this issue, we need to properly manage our references and prevent our script from accessing destroyed objects. We can start by nulling out references after calling Destroy:
Destroy(targetObject);
targetObject = null;
We should also guard every access with null checks to prevent errors when an object is unexpectedly destroyed:
if (targetObject == null) return;
For a more complete solution, we can implement a safer pattern for object destruction and reference management:
using UnityEngine;
public class SentryCube : MonoBehaviour
{
public GameObject projectile;
void Start()
{
// remove the projectile
Destroy(projectile);
// immediately clear the reference
projectile = null;
}
void Update()
{
// safe access pattern
if (projectile == null)
{
Debug.Log("Projectile already destroyed, skipping update");
return;
}
// do something with the projectile only if it is still alive
projectile.transform.Translate(Vector3.forward * Time.deltaTime);
}
}
With this approach, we destroy the projectile, clear the projectile reference, and check for a null reference before we attempt to access it. This prevents the MissingReferenceException and makes our code more robust.
Projectile Destroyed
Improving Unity error debugging and performance with Sentry
In Unity, finding the cause of errors can be tricky, and performance issues often accompany errors. This is where Sentry comes in.
Sentry for Unity provides real-time error tracking and performance monitoring that lets you do the following:
Capture exceptions automatically with detailed stack traces.
See the context in which errors occurred (such as the scene info and component state).
Track performance issues that might lead to errors.
Monitor errors across different platforms and devices.
Improve game performance by identifying bottlenecks.
Instead of waiting for players to report issues or spending hours reproducing elusive bugs, Sentry notifies you immediately when an error occurs and provides the context you need to fix it quickly.
Getting started with Sentry for Unity
Adding Sentry to your Unity project is straightforward. First, install the SDK through the Unity Package Manager:
Open the Package Manager (Window → Package Manager).
Click the + button and select Add package from git URL.
Enter: https://github.com/getsentry/unity.git#3.1.0.
Then configure the SDK with your Sentry project details:
using UnityEngine;
using Sentry;
public class SentryInit : MonoBehaviour
{
void Awake()
{
SentryOptions options = new SentryOptions
{
Dsn = "YOUR_DSN_HERE",
Debug = true,
EnableAutoSessionTracking = true,
AttachScreenshot = true,
CaptureInEditor = false
};
SentrySdk.Init(options);
}
void OnApplicationQuit()
{
SentrySdk.Close();
}
}
With this setup, Sentry automatically captures unhandled exceptions like our NullReferenceException and IndexOutOfRangeException.
For explicit error tracking, you can capture specific errors manually:
try
{
// Code that might cause an exception
GameObject.Find("NonExistentObject").GetComponent<Rigidbody>();
}
catch (System.Exception exception)
{
SentrySdk.CaptureException(exception);
}
For the MissingComponentException errors we discussed earlier, Sentry provides the full scene hierarchy at the time of the error, making it much easier to identify which GameObject is missing the required Component:
// Adding additional context to your errors
SentrySdk.ConfigureScope(scope =>
{
scope.SetTag("scene", UnityEngine.SceneManagement.SceneManager.GetActiveScene().name);
scope.SetTag("level", PlayerPrefs.GetInt("CurrentLevel").ToString());
scope.SetExtra("player_position", transform.position.ToString());
});
When errors occur, you’ll see detailed reports in the Sentry dashboard. These reports include:
The exact file and line number where the error happened
A snapshot of the scene hierarchy at the time of the error
Device-specific information for platform-dependent bugs
The user actions leading up to the crash (breadcrumbs)
Optional screenshots showing what the player was seeing
To learn more about how to use Sentry to monitor errors in your Unity games, check out our guide to using Sentry for error and crash reporting in Unity.