My use case: In my game I have an overlay that tracks any field with the '[TrackedField]' attribute. I want it to display the name of the variable, and the current value. Reflection being a bit of an expensive operation, I was looking for a way to retrieve the value once through reflection, and then make a delegate function, which doesn't use reflection, that returns the field's value. That way it can be called whenever I want to update that value on the overlay.
I actually don't know if what I'm asking is even possible, or if there would be a better way to retrieve this value. I've searched around for the past couple days, but all I was able to dig up was this related post. It will most likely be updated multiple times a second, so I'd like to avoid repeated use of reflection if I can.
Currently my code just gets every variable name (or a label defined in the attribute) and displays it with a dummy delegate that just reads "error":
MonoBehaviour[] sceneActive = GameObject.FindObjectsOfType<MonoBehaviour>();
foreach (MonoBehaviour mono in sceneActive)
{
System.Type monoType = mono.GetType();
// Retreive the fields from the mono instance
FieldInfo[] objectFields = monoType.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
// search all fields and find the attribute [TrackedField]
for (int i = 0; i < objectFields.Length; i++)
{
TrackedFieldAttribute attribute = Attribute.GetCustomAttribute(objectFields[i], typeof(TrackedFieldAttribute)) as TrackedFieldAttribute;
// if we detect any attribute add it to the overlay
if (attribute != null)
{
trackerBar.AddTab(attribute.label == null ? objectFields[i].Name : attribute.label, () => { return "error"; },attribute.color);
}
}
}
Here's an example of the '[TrackedField]' attribute in action:
[TrackedField]
private bool consoleOpen = false;
[TrackedField("MyLabel")]
private bool overlayShown = false;
[TrackedField("ColoredLabel", 50, 50, 255)]
It results in this on the overlay, if you were curious.
And if you were interested in what the attribute looked like:
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
public class TrackedFieldAttribute : Attribute
{
private string _label;
private Color _color;
public TrackedFieldAttribute()
{
_label = null;
_color = default(Color);
}
public TrackedFieldAttribute(string label)
{
_label = label;
_color = default(Color);
}
public TrackedFieldAttribute(float red = 0, float green = 0, float blue = 0)
{
_label = null;
_color = new Color(red / 255f, green / 255f, blue / 255f);
}
public TrackedFieldAttribute(string label, float red = 0, float green = 0, float blue = 0)
{
_label = label;
_color = new Color(red / 255f, green / 255f, blue / 255f);
}
public string label
{
get { return _label; }
set { _label = value; }
}
public Color color
{
get { return _color; }
set { _color = value; }
}
}