1
\$\begingroup\$

I'm creating a manager object that controls a bunch of other objects at once.

I want to be able to restrict / expose parameters in the target object to the manager via a custom attribute. I have the following working:

[AttributeUsage(AttributeTargets.Field)]
public class ManagableAttribute : Attribute {}

public class TargetObject : MonoBehaviour
{
    // public ObjectScript obj;
    
    [Managable]public float var1;
    public float var2;
}

Two variables in the target object, only one of which has the [Managable] attribute.

Based on some other posts I found, in the editor script I have it searching the fields in the target script and identifying the ones with the [Managable] attribute and printing them to the terminal:

[CustomEditor(typeof(TargetObject))]
[CanEditMultipleObjects]
public class ObjectManagerEditor : Editor
{
    public override void OnInspectorGUI()
    {
        TargetObject targetObject =  (TargetObject)target;

        //// Manually creating the variable floatfield i need
        //o.var1 = EditorGUILayout.FloatField("var1", o.var1);

        Type targetType = targetObject.GetType();
        FieldInfo[] objectFields = targetType.GetFields(BindingFlags.Instance | BindingFlags.Public);

        foreach (var field in objectFields)
        {
            ManagableAttribute thisAttribute = (ManagableAttribute)Attribute.GetCustomAttribute(field, typeof(ManagableAttribute));
            if (thisAttribute != null)
            {
                // Debug.Log(thisAttribute);
                var f = field;
                Debug.Log(field.Name);
            }
        }
    }
}

Can I have it create an EditorGUILayout.FloatField (or whatever type) in the loop for each variable it finds with the [Managable] attribute?

\$\endgroup\$
2
  • \$\begingroup\$ What have you tried to do to add an editor field for each of the fields you've found? \$\endgroup\$
    – user35344
    Nov 30 '21 at 17:35
  • \$\begingroup\$ var f = field.GetValue(targetObject); f = EditorGUILayout.FloatField("test", f); I can't seem to work out how to access the actual instance of the field on the target object via reflection in a way that I can attach to the editor field. \$\endgroup\$ Nov 30 '21 at 17:41
1
\$\begingroup\$

I have a feeling there's a better way but this seems to work

    public override void OnInspectorGUI()
    {   
        FieldInfo[] objectFields = targetType.GetFields(BindingFlags.Instance | BindingFlags.Public);

        foreach (var field in objectFields)
        {
            ManagableAttribute thisAttribute = (ManagableAttribute)Attribute.GetCustomAttribute(field, typeof(ManagableAttribute));
            if (thisAttribute != null)
            {
                float tempValue = EditorGUILayout.FloatField(field.Name, (float) field.GetValue(targetObject));
                field.SetValue(targetObject, tempValue);
            }
        }
    }
\$\endgroup\$
2
  • \$\begingroup\$ You might want to use SerializedProperties instead, to get proper support for undo, save/load, multi-object editing, etc. Making direct changes to the raw C# object without going through the Unity infrastructure can cause them to escape the editor's notice, so it doesn't know to serialize them into your scene file. \$\endgroup\$
    – DMGregory
    Nov 30 '21 at 19:56
  • \$\begingroup\$ That's great info thanks. \$\endgroup\$ Nov 30 '21 at 20:48

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .