- Home /
GetComponent does never return null, possible bug?
Hi,
I was trying to do create a function to check if a GameObject has a certain component and I found this weird bug in Unity. If someone could explain me what is going on, I'd be very happy.
Here's how to reproduce the problem:
1. Create a GameObject
2. Add script to GameObject
private void Awake()
{
Debug.Log(HasComponent<TextMesh>(gameObject));
}
private bool HasComponent<T>(GameObject go)
{
T component = go.GetComponent<T>();
return (component != null);
}
3. Try to start the game WITH AND WITHOUT a TextMesh component attached to the Game Object. You'll notice that both of the times the console will log 'True'.
This is really weird, is even returns true if you don't have a TextMesh component attached. This piece of code works with other components (for example Image), but I'm really wondering why it isn't working with the TextMesh component.
Thanks in advance again & kind regards,
Nathan
Answer by bobisgod234 · Feb 08, 2018 at 12:12 AM
Try it in a build. I have a feeling this is probably related to Unity's strange fake-null thing it returns when ran in the editor.
I took the liberty of converting your comment into an answer.. All i can add here is a "Yes", you are right ^^.
Now I know I'm not going crazy. Thank you for the answer.
As stated in the blog post, the ?? operator does a real null check.
Here is the solution to return the correct boolean value:
private bool HasComponent<T>(GameObject go) where T : Component
{
return go.GetComponent<T>() ?? false;
}
Sorry but you draw the wrong conclusion from your observations. The "null-coalescing", as you said, does an actual reference-null check. That means it won't detect fake null instances as null. Your problem is that your generic parameter T had no type constraint and therefore the compiler will use the default == or != operator which is the one of System.Object. This of course will see a fake null object as normal object since that's what it actually is. Unity's custom == operator only works for types derived from UnityEngine.Object.
A common solution is to do this:
T inst = go.GetComponent<T>();
return inst != null && !inst.Equals(null);
The first null check will catch actual null references. That means if inst is actually null it will return false. However if inst is an object it uses the Equals method to check for a fake null object.
However an easier solution for this specific case would be:
private bool HasComponent<T>(GameObject go)
{
return go.GetComponent(typeof(T)) != null;
}
This method will also work with interfaces. The trick is that the non generic version of GetComponent returns a "Component". Therefore the nullcheck will use unity's custom == / != operator.
"Unity's custom == operator only works for types derived from UnityEngine.Object."
The Text$$anonymous$$esh class is derived from UnityEngine.Object, right? So why wouldn't it work with a Text$$anonymous$$esh?
I'm trying to wrap my head around this fake null thing, it's hard to understand. The 'solution' I posed above your comment seems to work with whatever component I try. Why is it still incorrect? In what cases would my 'solution' be wrong?
"The trick is that the non generic version of GetComponent returns a "Component". Therefore the nullcheck will use unity's custom == / != operator."
If Components use unity's custom == / != operators, then why won't it work on the Text$$anonymous$$esh? Afterall, the Text$$anonymous$$esh is a Unity Component.
Your answer
Follow this Question
Related Questions
TextMeshPro Object not updating in real time 0 Answers
Access Violation (Read from location 00000000 caused an access violation) 1 Answer
Multiple Cars not working 1 Answer
Distribute terrain in zones 3 Answers
Photon networking doesn't sync 0 Answers