Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 12 Next capture
2021 2022 2023
1 capture
12 Jun 22 - 12 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
  • Help Room /
avatar image
2
Question by ayaraee · Sep 14, 2016 at 12:29 PM · c#coroutinecomponentcomponents

GetComponent returns null however comparison to null returns false

Look the result of the following function

         public static T FindComponent<T>(this GameObject obj) where T : class
         {
             T a = obj.GetComponent<T>(); // Shows as "null"
             T b = obj.GetComponentInChildren<T>(); // Some correct object
 
             T c = a ?? b; // c is set to a
             bool d = a == null; // false
             bool g = a != null; // true
             bool f = a.ToString() == "null"; // true
 
             return obj.GetComponent<T>() 
                 ?? obj.GetComponentInChildren<T>() 
                 ?? obj.GetComponentInParent<T>();
         }

a is essentially null but a == null returns false. Nevertheless debugger shows a to be null. If a code uses this function and attempts do use that component this exception is thrown:

MissingComponentException: There is no 'T' attached to the "[ObjectName]" game object, but a script is trying to access it. T being the component type passed to the function. I am clueless as to how this is even happening. Interesting thing is a.ToString() == "null" is true

Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

2 Replies

· Add your reply
  • Sort: 
avatar image
2
Best Answer

Answer by Bunny83 · Sep 14, 2016 at 06:14 PM

As NoseKills said the problem is that Unity has implemented a custom "==" operator for UnityEngine.Object. For all types which are derived from UnityEngine.Object the compiler will use that overloaded operator. However the operator selection is not dynamic. So the right operator is choosen at compile time.

Since you use a generic method here the actual type of "T" is not known at compile time. Your only constraint is "class" which restricts T to by a reference type. So the == operator used is the normal System.Object == operator and not Unity's == operator.

Try this:

 bool d = (UnityEngine.Object)a == null; 

It should return true for fake null objects.

You can't use the "null coalescing operator" ( ?? ) since it always uses the System.Object "==" operator.

So to get to a solution you should get rid of the "??" operators.

So one solution would be to change your generic constraint to "Component" instead of "class". This will make all "T" variables of type Component and ensures that "==" works.

However if you want to be able to pass interfaces as types, you either have to cast the result to UnityEngine.Object (or Component) and then do the check, or use "Equals"

btw: "GetComponentInChildren" will also do a GetComponent. The name is misleading but GetComponentInChildren will first look on the gameobject itself and then inside children.

 public static T FindComponent<T>(this GameObject obj) where T : class
 {
     T res = obj.GetComponentInChildren<T>();
     if (res != null && !res.Equals(null))
         return res;
     return obj.GetComponentInParent<T>();
 }

This should do what you want. The Equals check will tell you about "fake null" objects. Though you can only use Equals when you know the reference isn't actually null ^^. Equals is a virtual instance method, so it is dynamically dispatched.

Comment
Add comment · Show 2 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image ayaraee · Sep 15, 2016 at 02:44 PM 0
Share

Very good explanation, I had no idea the == replacement is deter$$anonymous$$ed at compile time. I followed the second path. Also I wish GetComponentInChildren was better named. Btw you mentioned passing interfaces. If I have component DoesX : $$anonymous$$onobehaviour, IDoesSomething and do GetComponent<IDoesSomething>() on the object that has the component attached, will it return the correct object? I thought GetComponent is limited to concrete types

avatar image Bunny83 ayaraee · Sep 15, 2016 at 06:19 PM 0
Share

In the past unity had a constraint on the generic parameter of all GetComponent methods. So it only allowed types derived from Component. However they removed it somewhere between unity4.5 and unity5.x

So yes, you can now directly use interfaces with GetComponent.

From a pure software design point of view the constraint was a logical thing. However since the generic version actually uses the System.Type version under the hood, the constraint had no benefit's. It just restricted the usage. Of course without the constraint you could also pass types which clearly aren't components, but that's also possible with the non generic version.

avatar image
2

Answer by NoseKills · Sep 14, 2016 at 04:43 PM

The fact alone that you get a MissingComponentException and not a NullReferenceException gives away a lot. In C#, if an object truly is null and you reference its members, you will get a genuine NullReferenceException. There's no way around it.

Unity does funky things when destroying or e.g GameObjectFind()ing non-existent UnityEngine.Object instances and that causes certain means of checking for null to return unexpected results. "??" is one of them.

Here's a blog post about it And here a forum post

Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Bunny83 · Sep 14, 2016 at 06:18 PM 0
Share

Unity, at least inside the Unity editor, will return fake null objects on purpose to actually create the "$$anonymous$$issingComponentException". So GetComponent will actually always return a value when you test inside the editor. Though when no component is found a fake null object is returned which, usually, is detected as null unless the reference get casted to System.Object for some reason.

Note: When you run a built, Unity doesn't create fake null objects on purpose anymore, however you can still come across these when an object is destroyed. References to UnityEngine.Objects pretend that they are null once you destroyed them.

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

7 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Generic use of Components through typeof(Component) | Convert from Unity's generic Component into a desired one 1 Answer

Edit variable of component by type 0 Answers

How would I figure out what type a component is,Getting the type of a component 1 Answer

EventManager : How to know when a co-routine (listened by multiple objects) ended? 0 Answers

How would i increase the speed of my enemies? Thanks 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges