| Keywords | null, ?., ??, ??=, int?, is null |
|---|---|
| Category | Type system |
| In Unity | Empty Inspector fields, destroyed objects, GetComponent finding nothing |
Null & Nullable Types
null means "this variable doesn't point to any object". Using a null variable causes the most common error in Unity, NullReferenceException. This page covers how to check for null safely, the ?. and ?? shortcuts, and the important Unity exception to those shortcuts.
A reference variable is a leash. Normally there's a dog on the end. null is an empty leash. Calling a method on it (dog.Bark()) is telling the empty leash to bark, and C# throws NullReferenceException because there's no dog to do it.
Checking for null
[SerializeField] private Transform target;
void Update()
{
if (target == null) return; // nothing to follow yet
transform.LookAt(target);
}
A good habit: check required references once in Awake and log a clear message, instead of letting a mystery error happen later.
void Awake()
{
if (target == null)
Debug.LogError($"{name}: 'target' is not assigned in the Inspector.", this);
}
Null shortcuts (for normal C# objects)
| Operator | Meaning | Example |
|---|---|---|
a?.B() | Call only if a isn't null; otherwise result is null | OnDied?.Invoke(); |
a ?? b | Use a, or b if a is null | string n = playerName ?? "Guest"; |
a ??= b | Assign b only if a is null | cache ??= new List<int>(); |
a is null / a is not null | Pure null check | if (data is null) return; |
The Unity exception: don't use these on Unity objects
GameObject, components, assets) that have been destroyed still exist as C# objects. Unity overrides == so destroyedObj == null returns true. The operators ?., ??, ??= and is null don't use that override, so they think a destroyed object is still alive.Destroy(enemy.gameObject);
// ...a frame later:
enemy?.TakeDamage(5); // BUG: calls TakeDamage on a destroyed object -> MissingReferenceException
if (enemy != null) enemy.TakeDamage(5); // CORRECT
var cam = customCam ?? Camera.main; // BUG if customCam was destroyed
var cam2 = customCam != null ? customCam : Camera.main; // CORRECT
if (enemy) { } // also correct: Unity objects convert to bool (false if null/destroyed)
Rule of thumb: Unity object → == null / != null. Plain C# object, event or delegate → any of the shortcuts. See also "fake null" on the Object page.
Nullable value types (int?, float?, Vector3?)
Value types like int and Vector3 can't normally be null. Add ? to allow it. Useful when "no value" is different from zero.
private Vector3? lastSeenPosition; // null = never seen the player
void Update()
{
if (CanSeePlayer())
lastSeenPosition = player.position;
if (lastSeenPosition.HasValue)
{
MoveTowards(lastSeenPosition.Value);
}
}
// Shorter:
float? bestTime = LoadBestTime(); // null = no record yet
float shown = bestTime ?? 0f; // ?? is fine: float? is not a Unity object
| Member | Description |
|---|---|
x.HasValue | true if it holds a value |
x.Value | The value. Throws InvalidOperationException if there is none. |
x.GetValueOrDefault() | The value, or 0/default if none |
Unity can't show nullable fields (int?) in the Inspector.
What happens at runtime
- A reference variable stores an address.
nullis address "nothing". - Calling a member on it makes the runtime detect the invalid access and throw
NullReferenceException. - For Unity objects, the C# object can outlive the native engine object. After
Destroy, the native part is gone; Unity's==checks for that. Accessing members then throwsMissingReferenceException. - An unassigned serialized field in the Editor may also be a "fake null" and throw
UnassignedReferenceException, whose message names the field. That's why the Editor's errors can be more helpful than a build's.
Common Mistakes
- Assuming GetComponent always succeeds. It returns null if the component isn't there. Use
TryGetComponentor[RequireComponent]. - Forgetting to assign an Inspector field. The #1 cause of
NullReferenceExceptionfor beginners. - Using a reference in Awake that another script sets in its Awake. Order between objects isn't guaranteed; use
Startfor cross-object references. ?.on Unity objects. See the warning above.
See also
- Exceptions & try/catch
- Value & Reference Types
- Object (fake null)
This page is a simplified, AI-assisted interpretation. For the complete and authoritative reference, see the official Microsoft C# documentation.