- Home /
Generic way to get properties on Component?
I need to dump selected GameObjects to a file, with all their components and their components variable names and values.
Is there a generic 'getAttribute' kind of API I can call if I have a Component and I don't know the type?
Answer by Mike 3 · Jul 26, 2010 at 08:01 PM
You could always abuse reflection and generics for it.
Something like:
using System.Reflection;
//blah blah
public static T GetReference<T>(object inObj, string fieldName) where T : class { return GetField(inObj, fieldName) as T; }
public static T GetValue<T>(object inObj, string fieldName) where T : struct { return (T)GetField(inObj, fieldName); }
public static void SetField(object inObj, string fieldName, object newValue) { FieldInfo info = inObj.GetType().GetField(fieldName); if (info != null) info.SetValue(inObj, newValue); }
private static object GetField(object inObj, string fieldName) { object ret = null; FieldInfo info = inObj.GetType().GetField(fieldName); if (info != null) ret = info.GetValue(inObj); return ret; }
This has the benefit of working on any object, not just components. Use GetValue when you know it'll be a value type, GetReference when it'll be a reference type. Added SetField just for fun too (which works without generics for obvious reasons)
Hopefully pretty self explanatory
Thanks $$anonymous$$ike. Had dug up an answer myself, posted before I saw your answer, but you've given me some good stuff to work with there.
Sure, why not? What's your code? if it's not directly related to this question / answer you should post your own question and include your code. What variable type are you trying to set?
Answer by DaveA · Jul 26, 2010 at 08:04 PM
This should get me started:
using UnityEngine; using UnityEditor; using System; using System.Reflection;
class Introspect {
[MenuItem("Window/Introspect")]
static void IntrospectNow()
{
bool found1;
GameObject[] go = Selection.gameObjects;
Transform[] trs = Selection.GetTransforms (SelectionMode.Deep | SelectionMode.DeepAssets);
found1 = false;
foreach (Transform tr in trs)
{
Component[] components = tr.GetComponents<Component>();
for (int i = 0; i < components.Length; i++)
{
Component c = components[i];
if (c == null)
{
Debug.Log(tr.name + " has an empty script attached in position: " + i);
found1 = true;
}
else
{
Type t = c.GetType();
Debug.Log("Type "+t);
Debug.Log("Type information for:" + t.FullName);
Debug.Log("\tBase class = " + t.BaseType.FullName);
Debug.Log("\tIs Class = " + t.IsClass);
Debug.Log("\tIs Enum = " + t.IsEnum);
Debug.Log("\tAttributes = " + t.Attributes);
System.Reflection.FieldInfo[] fieldInfo = t.GetFields();
foreach (System.Reflection.FieldInfo info in fieldInfo)
Debug.Log("Field:" +info.Name);
System.Reflection.PropertyInfo[] propertyInfo = t.GetProperties();
foreach (System.Reflection.PropertyInfo info in propertyInfo)
Debug.Log("Prop:"+info.Name);
Debug.Log("Found component "+c);
}
}
}
}
}
for the code blocks, just paste the code in, select all, then click the code button (button with 0s and 1s) - works a heck of a lot better than either pre or code tags
Answer by Cherno · Jul 19, 2015 at 08:35 PM
SerializeHelper can do what you ask for, at least for Transform and MonoBehavior components; Other types can be supported with some minor additions.