using UnityEngine;
using System.Collections;
public interface ICollide{
void PlayerHit(ControllerColliderHit hit);
}
void OnControllerColliderHit(ControllerColliderHit hit){
ICollide[] hitColliders = (ICollide[])hit.gameObject.GetComponents(typeof(ICollide));
for (int i = 0; i<hitColliders.Length; i++){
hitColliders[i].PlayerHit(hit);
}
}
Results in:
nvalidCastException: Cannot cast from source type to destination type.
PlayerController.OnControllerColliderHit (UnityEngine.ControllerColliderHit hit) (at Assets/Scripts/Systems/Player/PlayerController.cs:52)
UnityEngine.CharacterController:Move(Vector3)
UnityEngine.CharacterController:Move(Vector3)
PlayerController:Update() (at Assets/Scripts/Systems/Player/PlayerController.cs:47)
The same function and syntax works fine for getting classes, just not interfaces. Does anyone know how to use GetComponents with C# interfaces? [/code]
Its called GetComponent not GetSomething
That should already answer it
as such no, it won’t work with interfaces, it will only return classes of type Component or extending it (Behaviour and especially MonoBehaviour on which your whole functionality bases)
as for the technicals on why: cause your class does not register itself with the engine nor is it managed by it, but all components+ are.
You can replicate that by making an own manager that handles specific things of yours where interface implementing classes must register themself with your manager
GetComponent actually does work with interfaces , just not Get__Components__
Considering whatever the underlying functionality of GetComponent(s?) does work with interfaces, I was hoping it was some sort of syntax issue. Odd that GC works but GCs does not; oh well. In this particular case I don’t really need to work around it, I’ll just make the interface a MB extended class instead. Was mostly just curious for my other project which makes extensive use of interfaces.
A relatively easy workaround, for anyone interested, is to use GetComponent to return a list of all components on an object, and cast them to your interface.
Component[] hitComponents = hit.gameObject.GetComponents(typeof(ICollide));
Debug.Log(hitComponents.Length);
for (int i = 0; i<hitComponents.Length; i++){
if (hitComponents[i] is ICollide){
ICollide colInterface = hitComponents[i] as ICollide;
colInterface.PlayerHit(hit);
}
}
It should only be returning components which implement the interface (in this case, ICollide); however, I’d do a quick if (result is interface) anyway just to be sure.
Really? I can’t get that to work. I wouldn’t expect it to, but it would be great if it did work.
//This does not work:
Collider hitcollider = hitInfo.collider;
IArmored v = hitcollider.GetComponent<IArmored> ();
I get an error.
The type IArmored' must be convertible to UnityEngine.Component’ in order to use it as parameter T' in the generic type or method UnityEngine.Component.GetComponent()’
Do you have to derive the Interface from something specific? Anyone have a working example?
BTW, this is how I currently do it, where Entity derives from Component and IArmored is an Interface. Maybe there is a better way/
IArmored a = hitcollider.GetComponent<Entity> () as IArmored;
if (a != null) {
Debug.Log("Projectile hit IARMORED";
}
Get can impossibly work as you can’t assign IAttribute as a component cause it just is none unless there is a bug in 3.1 that allows stuff not derived from Component to be assigned as one
Also it sounds like an extremely clumsy and low performance solution for a problem where a trivial statc LinkedList attributes = new LinkedList(); in Attribute would do it too and that at a higher performance cause it requires no filtering etc
GetComponent(s) is still one of the slowest functions of all and on mobile too heavy to do it in realtime each frame for example
the attribute class i initially posted was a bit of a kludge and only necessary for situations where you needed to grab multiple components, which i hadn’t realized kyle had already covered the concept of. but this works, and it’s a pretty nice “bug” as designing for interfaces is far less clumsy than for individual components, and it can’t be slower than caching any other component reference from GetComponent as plenty of Unity developers see fit to do. i’d be interested to hear from someone at Unity if this functionality is intentional or not.
I’ve posted a few places about this tonight. I’m just hoping someone has an idea. I need to get the component which implements an interface. This is in an OnTriggerEnter(Collider other). Any ideas?
I’m open to any pattern, even if it doesn’t use GetComponent. I could use a class but it would have to be spliced in to a class tree at the uppermost level since .Net doesn’t support multiple inheritance. We want to release this tool to the Unity-public, so an Interface is by far the most elegant way to instruct people to snap on this solution.
public static T GetInterface<T>(this GameObject inObj) where T : class
{
return inObj.GetComponents<Component>().OfType<T>().FirstOrDefault();
}
public static IEnumerable<T> GetInterfaces<T>(this GameObject inObj) where T : class
{
return inObj.GetComponents<Component>().OfType<T>();
}
Here are more restrictive versions that actually check if is a interface and wont allow classes to return!
public static T GetInterface<T>(this GameObject inObj) where T : class
{
if (!typeof(T).IsInterface) {
Debug.LogError(typeof(T).ToString() + ": is not an actual interface!");
return null;
}
return inObj.GetComponents<Component>().OfType<T>().FirstOrDefault();
}
public static IEnumerable<T> GetInterfaces<T>(this GameObject inObj) where T : class
{
if (!typeof(T).IsInterface) {
Debug.LogError(typeof(T).ToString() + ": is not an actual interface!");
return Enumerable.Empty<T>();
}
return inObj.GetComponents<Component>().OfType<T>();
}
If u restrict it to Component or just Monobehaviours is up to u. I suspect thats essentially the same that the none generic version for GetComponents(type) does, i rather use a clean named function than relying on the “strange” behavior of GetComponents, since the generic and none generic version should behave the same.
2014, This feature is still available :). I was able to Invert Control so that I can attack new funcitonality dynamically without changin old legecy source code.
Now implemened in Unity 4.6 apparently. From the release notes:
Added smart-allocating GetComponents method which fetches components of type T and grows the list as needed. Non-generic version that supports interfaces has also been added.
There’s nothing in the documentation regarding usage of this non-generic GetComponents. Has it been removed?
Edit: Figured it out, now I’m just gonna post a quick breakdown for posterity–
This doesn’t work:
Where IActionable is an interface you’ve defined. This DOES work:
List<IActionable> Actionables
Component[] comps = gameObject.GetComponents(typeof(IActionable));
foreach (Component com in comps)
Actionables.Add(com as IActionable);