Runtime exceptions
UnassignedReferenceException: The variable 'X' of 'Y' has not been assigned.
The exact message
UnassignedReferenceException: The variable 'X' of 'Y' has not been assigned.Variants of this message
- UnassignedReferenceException
- has not been assigned.
- You probably need to assign the variable in the inspector.
- You probably need to assign the 'X' variable of the 'Y' script in the inspector.
What it means
A serialised field that Unity expected you to fill in the Inspector is empty. Unity throws this rather than a plain NullReferenceException because it can see the field was meant to be assigned in the editor, and the message names both the variable and the script so you can go straight to it. The interesting cases are the ones where you are certain you did assign it, which almost always come down to assigning it on the wrong object.
Causes and fixes
Ranked by how often they actually occur, most common first.
The field is genuinely empty in the Inspector
The straightforward case, and the one the message describes. A public or [SerializeField] field shows as None in the Inspector until something is dragged into it. Adding a new field to a script that is already used in several places is the usual trigger, because existing objects keep their saved data and the new field starts empty on all of them.
The fix: Read the variable name and script name from the message, select the object, and fill the field. Where the error names an object you cannot find, the log entry is clickable and will select it in the Hierarchy.
Source: Unity Manual: Null references
You assigned it on the prefab instance, not the asset
Dragging a reference onto a prefab instance in the scene creates an override on that one instance. Objects spawned from the prefab asset at runtime do not carry it, so the spawned copies throw while the one you set up works perfectly. The reverse also happens: assigning on the asset while the scene instance carries an older override that is still empty.
The fix: Open the prefab in Prefab Mode and assign the field there, so every instance inherits it. Where an instance already has an override, use the Overrides dropdown on the instance to see what differs and revert it.
Source: Unity Manual: Editing a prefab in Prefab Mode, Unity Discussions: prefabs not saving reference to gameObject
A prefab asset cannot hold a reference to a scene object
A prefab lives in the Project window and has no knowledge of any particular scene, so Unity cannot serialise a reference from a prefab asset to an object that only exists in a scene. Attempting it in the Inspector either refuses the drop or silently leaves the field empty, and the spawned object then throws. This is a structural limit rather than a bug, and it catches people who expect the assignment to behave like any other.
The fix: Invert the direction. Have the scene object find or register itself with the spawned instance after Instantiate, or resolve the dependency at runtime through a manager the prefab can reach. Assigning the reference immediately after Instantiate is the simplest form.
The spawner lives in the scene, so it can hold both references and connect them.
using UnityEngine; public class EnemySpawner : MonoBehaviour { [SerializeField] private Enemy enemyPrefab; // project asset [SerializeField] private Transform player; // scene object public Enemy Spawn(Vector3 position) { Enemy enemy = Instantiate(enemyPrefab, position, Quaternion.identity); // The prefab asset could never have stored this itself. enemy.SetTarget(player); return enemy; } } public class Enemy : MonoBehaviour { private Transform target; public void SetTarget(Transform value) => target = value; }Source: Unity Manual: Prefabs
The field was hidden or renamed, losing its serialised value
Unity serialises fields by name. Renaming a field in code makes the old saved value orphaned and the new field starts empty, on every object using the script at once. Changing a field's type, or moving it behind a condition that stops it being serialised, has the same effect.
The fix: Add [FormerlySerializedAs("oldName")] above the renamed field so Unity carries the existing value across. Add it before the rename reaches anyone else's working copy, because it only helps for data that has not already been re-saved.
FormerlySerializedAs preserves data that would otherwise be lost on rename.
using UnityEngine; using UnityEngine.Serialization; public class HealthBar : MonoBehaviour { // Renamed from "img" to "fillImage"; existing scenes and prefabs keep // their assigned value because of the attribute. [FormerlySerializedAs("img")] [SerializeField] private UnityEngine.UI.Image fillImage; }
How to prevent it
Validate required references in Awake and disable the component when one is missing. Passing the component as the second argument to Debug.LogError makes the console entry clickable, which turns a hunt through the Hierarchy into one click.
Assign prefab fields in Prefab Mode rather than on an instance, and treat instance overrides as deliberate exceptions rather than the normal way to configure something.
Add [FormerlySerializedAs] whenever you rename a serialised field, and remove it once every scene and prefab has been re-saved. Renaming without it silently empties the field everywhere.
Where a reference is required for a component to work at all, consider whether it can be resolved in Awake instead. A GetComponentInChildren call that cannot fail is better than a field a human has to remember to fill.
Unity version differences
Behaviour is unchanged across supported Unity versions. Prefab Mode and the Overrides dropdown referenced above have been present since the prefab workflow rewrite in Unity 2018.3.
Related errors
- NullReferenceExceptionWhy Unity throws NullReferenceException, how to read the stack trace to find the exact line, and the five causes that account for nearly all of them.
- MissingReferenceExceptionWhy Unity says an object has been destroyed but you are still accessing it, how destroyed objects differ from null, and the four causes worth checking.
- Referenced script is missingWhy Unity reports a missing script on a GameObject, how to find which object it is, and the five causes from deleted files to broken .meta GUIDs.