Here is a class full of extension methods that I use to access components on gameobjects in a more OOP/C# style.
It includes support for accesssing components as interfaces.
using UnityEngine;
using System.Collections.Generic;
namespace com.spacepuppy.Utils
{
public static class ComponentUtil
{
#region Component Methods
public static bool IsComponentSource(object obj)
{
return (obj is GameObject || obj is Component);
}
#region HasComponent
public static bool HasComponent<T>(this GameObject obj) where T : Component
{
return (obj.GetComponent<T>() != null);
}
public static bool HasComponent<T>(this Component obj) where T : Component
{
return (obj.GetComponent<T>() != null);
}
public static bool HasComponent(this GameObject obj, string tp)
{
return (obj.GetComponent(tp) != null);
}
public static bool HasComponent(this Component obj, string tp)
{
return (obj.GetComponent(tp) != null);
}
public static bool HasComponent(this GameObject obj, System.Type tp)
{
return (obj.GetComponent(tp) != null);
}
public static bool HasComponent(this Component obj, System.Type tp)
{
return (obj.GetComponent(tp) != null);
}
public static bool HasComponentOfInterface<T>(this GameObject obj)
{
foreach (var comp in obj.GetComponents<Component>())
{
if (comp is T) return true;
}
return false;
}
public static bool HasComponentOfInterface<T>(this Component obj)
{
foreach (var comp in obj.GetComponents<Component>())
{
if (comp is T) return true;
}
return false;
}
public static bool HasComponentOfInterface(this GameObject obj, System.Type tp)
{
foreach (var comp in obj.GetComponents<Component>())
{
if (ObjUtil.IsType(comp.GetType(), tp)) return true;
}
return false;
}
public static bool HasComponentOfInterface(this Component obj, System.Type tp)
{
foreach (var comp in obj.GetComponents<Component>())
{
if (ObjUtil.IsType(comp.GetType(), tp)) return true;
}
return false;
}
#endregion
#region AddComponent
public static T AddOrGetComponent<T>(this GameObject obj) where T : Component
{
if (obj == null) return null;
T comp = obj.GetComponent<T>();
if (comp == null)
{
comp = obj.AddComponent<T>();
}
return comp;
}
public static T AddOrGetComponent<T>(this Component obj) where T : Component
{
if (obj == null) return null;
T comp = obj.GetComponent<T>();
if (comp == null)
{
comp = obj.gameObject.AddComponent<T>();
}
return comp;
}
public static Component AddOrGetComponent(this GameObject obj, System.Type tp)
{
if (obj == null) return null;
if(!ObjUtil.IsType(tp, typeof(ComponentUtil))) return null;
var comp = obj.GetComponent(tp);
if (comp == null)
{
comp = obj.AddComponent(tp);
}
return comp;
}
public static Component AddOrGetComponent(this Component obj, System.Type tp)
{
if (obj == null) return null;
if(!ObjUtil.IsType(tp, typeof(ComponentUtil))) return null;
var comp = obj.GetComponent(tp);
if (comp == null)
{
comp = obj.gameObject.AddComponent(tp);
}
return comp;
}
#endregion
#region GetComponent
// ############
// GetComponent
// #########
public static bool GetComponent<T>(this GameObject obj, out T comp) where T : Component
{
comp = obj.GetComponent<T>();
return (comp != null);
}
public static bool GetComponent<T>(this Component obj, out T comp) where T : Component
{
comp = obj.GetComponent<T>();
return (comp != null);
}
public static bool GetComponent(this GameObject obj, string tp, out Component comp)
{
comp = obj.GetComponent(tp);
return (comp != null);
}
public static bool GetComponent(this Component obj, string tp, out Component comp)
{
comp = obj.GetComponent(tp);
return (comp != null);
}
public static bool GetComponent(this GameObject obj, System.Type tp, out Component comp)
{
comp = obj.GetComponent(tp);
return (comp != null);
}
public static bool GetComponent(this Component obj, System.Type tp, out Component comp)
{
comp = obj.GetComponent(tp);
return (comp != null);
}
// ############
// GetFirstComponent
// #########
public static T GetFirstComponent<T>(this GameObject obj) where T : Component
{
if (obj == null) return default(T);
var arr = obj.GetComponents<T>();
if (arr != null arr.Length > 0)
return arr[0];
else
return default(T);
}
public static T GetFirstComponent<T>(this Component obj) where T : Component
{
if (obj == null) return default(T);
var arr = obj.GetComponents<T>();
if (arr != null arr.Length > 0)
return arr[0];
else
return default(T);
}
public static T GetFirstComponentOfInterface<T>(this GameObject obj)
{
if (obj == null) return default(T);
foreach (object comp in obj.GetComponents<Component>())
{
if (comp is T) return (T)comp;
}
return default(T);
}
public static T GetFirstComponentOfInterface<T>(this Component obj)
{
if (obj == null) return default(T);
foreach (object comp in obj.GetComponents<Component>())
{
if (comp is T) return (T)comp;
}
return default(T);
}
public static bool GetFirstComponentOfInterface<T>(this GameObject obj, out T comp )
{
comp = default(T);
if (obj == null) return false;
foreach (object c in obj.GetComponents<Component>())
{
if (comp is T)
{
comp = (T)c;
return true;
}
}
return false;
}
public static bool GetFirstComponentOfInterface<T>(this Component obj, out T comp)
{
comp = default(T);
if (obj == null) return false;
foreach (object c in obj.GetComponents<Component>())
{
if (c is T)
{
comp = (T)c;
return true;
}
}
return false;
}
// ############
// GetComponents
// #########
public static T[] GetComponentsOfInterface<T>(this GameObject obj)
{
if (obj == null) return null;
var lst = new List<T>();
foreach (object comp in obj.GetComponents<Component>())
{
if (comp is T) lst.Add((T)comp);
}
return lst.ToArray();
}
public static T[] GetComponentsOfInterface<T>(this Component obj)
{
if (obj == null) return null;
var lst = new List<T>();
foreach (object comp in obj.GetComponents<Component>())
{
if (comp is T) lst.Add((T)comp);
}
return lst.ToArray();
}
#endregion
#region RemoveComponent
public static void RemoveComponent<T>(this GameObject obj) where T : Component
{
var comp = obj.GetComponent<T>();
if (comp != null) Object.Destroy(comp);
}
public static void RemoveComponent<T>(this Component obj) where T : Component
{
var comp = obj.GetComponent<T>();
if (comp != null) Object.Destroy(comp);
}
public static void RemoveComponent(this GameObject obj, string tp)
{
var comp = obj.GetComponent(tp);
if (comp != null) Object.Destroy(comp);
}
public static void RemoveComponent(this Component obj, string tp)
{
var comp = obj.GetComponent(tp);
if (comp != null) Object.Destroy(comp);
}
public static void RemoveComponent(this GameObject obj, System.Type tp)
{
var comp = obj.GetComponent(tp);
if (comp != null) Object.Destroy(comp);
}
public static void RemoveComponent(this Component obj, System.Type tp)
{
var comp = obj.GetComponent(tp);
if (comp != null) Object.Destroy(comp);
}
public static void RemoveFromOwner(this Component comp)
{
Object.Destroy(comp);
}
#endregion
#endregion
}
}
and you can say:
var enemy = target.GetFirstComponet<Enemy>();//no matter if it's FootSoldier or MilitiaMan, you get it back
Do keep in mind, when you have 2 components that extend the same type. They BOTH can be put on the same gameobject. This is why it’s GetFirstComponent. You should avoid adding multiple components like this…
To allow it though, I’ve been working on a wrapper component that delegates calls to multiple components of similar types on a gameobject. I just don’t have the design down yet.
I also have this other function that based off some odd utilities I have allows me to ‘castTo’ between different component types. What it really does is just takes in any kind of object, and will grab the gameobject, component, component as interface, or convert it to a primitive type, based on what it is, and what it’s changing to.
/// <summary>
/// Unique casting routine that will allow for casting between components of a gameobject
/// this allows you to treat a gameobject as its component...
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="obj"></param>
/// <returns></returns>
public static T CastTo<T>(object obj)
{
if (obj is T) return (T)obj;
var tp = typeof(T);
if (ObjUtil.IsType(tp, typeof(Component)) GameObjectUtil.IsGameObjectSource(obj))
{
var go = GameObjectUtil.GetGameObjectFromSource(obj);
object comp = go.GetComponent(tp);
return (T)comp;
}
if (ConvertUtil.IsSupportedType(tp))
{
return ConvertUtil.ToPrim<T>(obj);
}
return default(T);
}
It requires some other util classes that I have including ConvertUtil (converts values between prim types), ObjUtil (Type reflection utility), GameObjectUtil (gameobject utility).
It’s useful for dealing with components as interfaces. I can retrieve objects in wrappers, as components, as gameobejcts, as whatever, as long as they implement an interface. And I may want to convert to another quickly.
//obj could be a transform, a gameobject, a component, or even a generic object that implements an interface that describes a component
void DoSomething(Object obj)
{
var comp = CastTo<ISomeComponent>(obj);
}
Now yes, all these functions have overhead. Sometimes a high processing overhead. So you shouldn’t just be using them all willy nilly. But they really help in cleaning up the code and allowing me to use interfaces and abstract classes a lot… which I do in most of my design patterns.