Colored Inspector Fields

Imagine a component, like a PopUp Window with many fields that you need to set. It might be hard to spot an unassigned field among them.

Wouldn’t it be nice if the unassigned field were highlighted, like this:

Of course, it would! So let’s see how we can do it!

We will make use of the Property Drawer, just like we did with the [ReadOnly] attribute. The first thing we need to do is to create a class that will inherit from PropertyDrawer. This class will have only one public variable: color.

using UnityEngine;

public class RequiredField : PropertyAttribute
{
    public Color color;
}

Next create a new script inside an Editor folder, just like we did with the [ReadOnly] attribute. Similarly, this script should inherit from the PropertyDrawer class, override the OnGUI() function, and has to have a [CustomPropertyDrawer] attribute:

using UnityEngine;
using UnityEditor;

[CustomPropertyDrawer(typeof(RequiredField))]
public class RequiredFieldDrawer : PropertyDrawer
{
    public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    {
        
    }
}

Inside the OnGUI() function first, we need to get the [RequiredField] attribute.

using UnityEngine;
using UnityEditor;

[CustomPropertyDrawer(typeof(RequiredField))]
public class RequiredFieldDrawer : PropertyDrawer
{
    public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    {
        RequiredField field = attribute as RequiredField;
    }
}

To check if the property was assigned we will make use of property.objectReferenceValue. Then we will pain the property field to the color value of the field variable if it is not assigned:

using UnityEngine;
using UnityEditor;

[CustomPropertyDrawer(typeof(RequiredField))]
public class RequiredFieldDrawer : PropertyDrawer
{
    public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    {
        RequiredField field = attribute as RequiredField;
        
        if(property.objectReferenceValue == null)
        {
            GUI.color = field.color; //Set the color of the GUI
            EditorGUI.PropertyField(position, property, label); //Draw the GUI
            GUI.color = Color.white; //Reset the color of the GUI to white
        }
        else
            EditorGUI.PropertyField(position, property, label);
    }
}

And that is all. Test it on any nullable public field, like a GameObject or a Transform.

public class HighlightTest : MonoBehaviour
{
    [RequiredField]
    public GameObject shouldBeAssigned;
    [RequiredField]
    public Transform yellowField;
    [SerializeField, RequiredField]
    private GameObject[] serializedHighlight;
}

Assign this script to any game object in the scene, and here is what you should see:

If you are OK with only one color then you can use this attribute as it is. However, if you want to have a more colorful inspector, then keep reading.

To set the color variable we can create a constructor for the [RequiredField] class, pass a Color as an argument and done with it:

using UnityEngine;

public class RequiredField : PropertyAttribute
{
    public Color color;

    public RequiredField(Color _color)
    {
        color = _color;
    }
}

Except it won’t work. You cannot pass a Color as an attribute parameter type. As a workaround let’s create an enum:

public enum FieldColor
{
    Red,
    Green,
    Blue,
    Yellow
}

Then the constructor will get a FieldColor as an argument, and we will set the color variable with a switch – case:

using UnityEngine;

public class RequiredField : PropertyAttribute
{
    public Color color;

    public RequiredField(FieldColor _color = FieldColor.Red)
    {
        switch (_color)
        {
            case FieldColor.Red:
                color = Color.red;
                break;
            case FieldColor.Green:
                color = Color.green;
                break;
            case FieldColor.Blue:
                color = Color.blue;
                break;
            case FieldColor.Yellow:
                color = Color.yellow;
                break;
            default:
                color = Color.red;
                break;
        }
    }
}

By default, the attribute color will be red, and we will have the option to override the color if we want to:

public class HighlightTest : MonoBehaviour
{
    [RequiredField]
    public GameObject shouldBeAssigned;
    [RequiredField(FieldColor.Yellow)]
    public Transform yellowField;
    [SerializeField, RequiredField(FieldColor.Blue)]
    private GameObject[] serializedHighlight;
}

The inspector will look like this:

And if you assign some of the fields:

The unassigned fields are clearly visible!

If you are too lazy to write the code, you can get it as a part of the ExtraTools project. Also, you can add the ExtraTools as a package to your project using PackageManager from this repository.

Leave a Reply

Your email address will not be published.