What exactly GetComponent returns?
Unity’s GetComponent behaves differently for engine components and your own MonoBehaviours. In the Editor, missing engine components like Renderer can yield a special “fake null” object that overrides ==, while in Standalone it’s a real null; your own types return real null in both. The post walks through logs and explains why (and how TryGetComponent differs), so you can write reliable null checks across environments.
Jun 5, 2022
Hello, Unity friends. I’m sure you use GetComponent<T>() every single day. But have you ever paid close attention to what it returns? Let’s delve into that!
Imagine this scenario: we have two classes derived from MonoBehaviour: MyClassA and MyClassB. Additionally, in our scene, there’s a GameObject. The only script attached to this GameObject is MyClassA — nothing else, no other components or scripts.
Now, let’s attempt to call GetComponent<MyClassB>() and GetComponent<Renderer>() from within the MonoBehaviour MyClassA. It looks something like this:
using UnityEngine;
namespace GetComponentExample
{
public class MyClassA : MonoBehaviour
{
private void Start()
{
//Some class nested from MonoBehaviour
//Or HingeJoint, Or MeshFilter, etc.
var notExistingMonobehaviour = GetComponent<MyClassB>();
var notExistingRenderer = GetComponent<Renderer>();
Debug.LogWarning(notExistingMonobehaviour == null);
Debug.LogWarning((object)notExistingMonobehaviour == null);
Debug.LogWarning(notExistingRenderer == null);
Debug.LogWarning((object)notExistingRenderer == null);
TryGetComponent<MyClassB>(out var stillNotExistingMonobehaviour);
TryGetComponent<Renderer>(out var stillNotExistingRenderer);
Debug.LogWarning(stillNotExistingMonobehaviour == null);
Debug.LogWarning((object)stillNotExistingMonobehaviour == null);
Debug.LogWarning(stillNotExistingRenderer == null);
Debug.LogWarning((object)stillNotExistingRenderer == null);
}
}
}
The question is: What will be printed in Debug.Log() in Editor and in Standalone Build and why? Take some time to think about it, please, and If you have already answered, let’s check your answer:
The Editor Log: True, True, True, False, True, True, True, True
The Standalone Build Log: True, True, True, True, True, True, True, True.
Editor Log:
So, why does this code returns True in Editor and Standalone:
And this one returns False in Editor and True in Standalone:
The result of calling GetComponent<Renderer>() is intriguing; it returns not a typical null, but a “fake” null object. This peculiar behavior involves an overridden == operator for null checks. The Unity Editor allocates this object for Unity components like Renderer, MeshFilter, HingeJoint, etc.
However, this fake null object is not allocated for the Standalone build.
On the other hand, GetComponent<MyClassB>() returns a real null in both the Editor and Standalone builds.
What about TryGetComponent? This method behaves differently: it always assigns a real null to its out parameter and never allocates a fake null object. Thus, when deciding between GetComponent and TryGetComponent, be mindful of the nuances in the results they return.

