- Home /
HasComponent
0 down vote favorite
So I am writing a method to check if a gameObject has a component.
Here it is:
public static bool HasComponent (this GameObject obj)
{
return obj.GetComponent<T>() != null;
}
And I'm using it like this:
void Update()
{
if (Input.GetKey("w"))
{
if (gameObject.HasComponent<Rigidbody>())
{
print("Has a rigid body.");
return;
}
print("Does not have rigid body.");
}
}
The gameObject does NOT have a rigid body but it is still printing that it does have.
edit your question, replace your code with your actual code and format it as code. The generic parameters are missing because you haven't formatted your code as code.
You have to select your code in your post and press the "101 / 010" button at the top. See the user guide section "Posting Questions, Answers and Comments".
There done. $$anonymous$$ay you please help now
Answer by Bunny83 · Feb 03, 2016 at 02:07 AM
Well, i guess your method definition looks like this:
public static bool HasComponent<T> (this GameObject obj)
{
return obj.GetComponent<T>() != null;
}
in which case you run into a nasty edge case problem. In the past this definition wouldn't compile since GetComponent used to have a contraint on the generic parameter to only allow types derived from Component.
Unity seem to have changed the definition and removed the constraint. This allows us to also use interfaces which is great.
However in your case the problem (which only occurs in the editor btw) is, that the "!=" check in your generic method most likely does a "System.Object" comparison. When testing inside the editor GetComponent will always return an instance. However that instance usually pretends to be null. This is done by overloading the "UnityEngine.Object" "==" and "!=" operators. Since your generic method doesn't use that specific operator it actually sees that fake-null object which of course is not null.
The problem shouldn't occur in a built version of your game.
There are several ways to make it work inside the editor as well:
First, add a constraint to "Component":
public static bool HasComponent<T> (this GameObject obj) where T : Component
{
return obj.GetComponent<T>() != null;
}
this will make the generic method to use the overloaded operators. However doing so prevents you from using interfaces with your method.
Another way would be to simply do an "as-cast" to ensure the right type:
public static bool HasComponent<T> (this GameObject obj)
{
return (obj.GetComponent<T>() as Component) != null;
}
This should work with all cases.
Another one would be
public static bool HasComponent<T> (this GameObject obj)
{
return obj.GetComponent(typeof(T)) != null;
}
The System.Type version of GetComponent always returns a Component. Since you don't use the actual type it's not necessary to use the generic version.
Answer by JoshuaMcKenzie · Feb 03, 2016 at 01:36 AM
the function definition is still missing the <T>
in ..
public static bool HasComponent (this GameObject obj)
plus you possibly want constraints too (which should prevent invalid calls like HasComponent<int>()
) and have it also extend Component instead to let pretty much anything that has a GetComponent<T>()
have this function too
public static bool HasComponent<T> (this Component obj) where T:class
$$anonymous$$y apologies, I did declare it with a . But I still do not get what you meant. Here is my current code:
public static bool HasComponent<T>(this GameObject obj) where T : class
{
return obj.GetComponent<T>() != null;
}
Answer by kevinrocks_786 · Feb 03, 2016 at 02:10 AM
So it worked perfectly when I replaced the
where T : class
//With
where T : Component
Your answer
Follow this Question
Related Questions
Multiple Cars not working 1 Answer
Distribute terrain in zones 3 Answers
Generic Component Declaration 1 Answer
Why we have to use getcomponent instead of a simple reference ? 2 Answers