- Home /
How to get the first component that implements a specific interface ?
Is there a beter (more style / more performant) way of getting the first (and hopefully only) component that implements a specific interface ?
public interface IFoo { void iFooMethod(); }
public class Foo { void OnCollisionEnter(Collision collision) { IFoo fooObject = null; MonoBehaviour[] components = collision.transform.root.GetComponents(); foreach(MonoBehaviour component in components) if(component is IFoo) { fooObject = component as IFoo; break; } if(fooObject != null) fooObject.iFooMethod(); } }
It just feels like I'm missing something ala GetComponentWithInterface.Blockquote
Answer by Andy-Block · Sep 22, 2013 at 08:27 PM
You can't use the generic method, but this form seems to work fine:
IFoo foo = (IFoo)gameObject.GetComponent(typeof(IFoo));
Probably too late for the OP, but perhaps this helps someone else :) .
YES! this was what i was looking for. very good! thank you. (i cant up-vote because i don't have enough reputation, sorry)
You can actually use the generic method – gameObject.GetComponent<IFoo>()
– in Unity 5 now, too :)
Answer by chris-nolet · Jun 20, 2016 at 08:01 PM
As of Unity 5, you can use the generic form of GetComponent
on interfaces:
IFoo foo = gameObject.GetComponent<IFoo>();
IFoo[] foos = gameObject.GetComponents<IFoo>();
Alternatively, .GetComponent(typeof(IFoo))
works for old versions of Unity and .GetComponents(typeof(IFoo))
(with an 's') also works from Unity 4.6 onwards.
Shouldn't that be:
IFoo[] foos = (IFoo[])gameObject.GetComponents<IFoo>();
For the second version?
Quite right – thanks! I've updated the answer. $$anonymous$$uch appreciated!
Answer by _Petroz · Jan 21, 2011 at 08:20 PM
I beleive that whole code block could be condensed down to the following:
void OnCollisionEnter(Collision collision)
{
collision.transform.root.GetComponent<IFoo>().iFooMethod();
}
$$anonymous$$mhm no, that's what I tried originally but: The type IFoo' must be convertible to
UnityEngine.Component' in order to use it as parameter T' in the generic type or method
UnityEngine.Component.GetComponent()'
Which makes sense since an interface cannot be a$$anonymous$$onoBheaviour (a child of I mean).
I see what you mean, I didn't realize 'interface' had a special meaning in C#, I thought you were just referring to an abstract base class. In that case I think the code you have is the best you will get. All I could suggest is wrapping it in a function to reduce the boiler plate in the classes using this code.
Yap, exactly what I did. The logic got a little more complicated so I moved everything to a new method in the superclass. Right now I don't think in my case a GetComponentsWithInterface() would help anymore, but kinda drives my attention that there's nothing to do it automagically. Cheers.
Answer by josephquested · Aug 21, 2020 at 08:06 AM
y'all are making it way too complicated. this works perfectly:
public class Hit : MonoBehaviour
{
void OnTriggerEnter(Collider other)
{
if (other.GetComponent<IDamageable>() != null)
{
print("HIT INTERFACE");
}
}
}
You missed the point pretty much. Back then when the question was asked the generic version of GetComponent has a constraint to "Component". This made it impossible to use an interface as type argument and you had to use the System.Type version instead and cast the result. This is what Andy-Block's answer said. Later Unity removed the constraint to allow interfaces. This is what chris-nolet's answer said.
The question was about getting the first component with a certain interface in order to call a method on it. In which way are the other answers more complicated? In your answer you don't even call any method and just check if such a component exists. I also don't see how this is any new information compared to the answer of chris.