Back to Blog Home

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:

  1. NullReferenceException: Object reference not set to an instance

  2. IndexOutOfRangeException: Array index problems

  3. MissingComponentException: Component not found

  4. MissingReferenceException: Destroyed object access

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.

1. How to fix NullReferenceException in Unity: Object reference not set to an instance

The problemJump To Solution

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:

Click to Copy
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:

Click to Copy
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:

Click to Copy
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.


2. What causes Array index is out of range errors in Unity?

We see this error when our code attempts to access an array or list element that doesn’t exist:

Click to Copy
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:

Click to Copy
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.

Click to Copy
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.


3. How to fix a MissingComponentException

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:

Click to Copy
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:

Click to Copy
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:

Click to Copy
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:

Click to Copy
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

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:

Click to Copy
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:

Click to Copy
Destroy(targetObject);
targetObject = null;

We should also guard every access with null checks to prevent errors when an object is unexpectedly destroyed:

Click to Copy
if (targetObject == null) return;

For a more complete solution, we can implement a safer pattern for object destruction and reference management:

Click to Copy
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:

Click to Copy
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:

Click to Copy
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:

Click to Copy
// 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.

Share

Share on Twitter
Share on Bluesky
Share on HackerNews
Share on LinkedIn

Published

Sentry Sign Up CTA

Code breaks, fix it faster

Sign up for Sentry and monitor your application in minutes.

Try Sentry Free

Topics

How Anthropic solved scaling log volume with Sentry

How Anthropic solved scaling log volume with Sentry

Listen to the Syntax Podcast

Of course we sponsor a developer podcast. Check it out on your favorite listening platform.

Listen To Syntax
© 2025 • Sentry is a registered Trademark of Functional Software, Inc.