50 Unity Tips #25: Property Drawers
Unity UnityTipsTricks UnityToolsProperty Drawers are used to customize the look of certain controls in the Inspector window or the look of a Serializable class itself. Unlike Custom Editors which customize a single MonoBehavior or ScriptableObject, Property Drawers customize the look of every instance of the Serializable class. Moreover, by using custom PropertyAttributes, the look of all class properties with a specified attribute can be easily customized.
Serializable Class
The look of a Serializable class can be customized by writing a Property Drawer. Although this may seem identical to #17-CustomEditor where we customized how the EnemyData SerializedObject appeared in the inspector, there is a major difference: Custom Editors are used to draw a UnityEngine.Object class in full while Property Drawers are used to draw a nested class or struct inside a UnityEngine.Object.
For more information check out the Unity Manual and this forum post.
Custom Attributes
In #15-PimpTheInspector we discussed the [HideInInspector], [Range] and [TextArea] attributes which hide properties from the inspector, displayed a min/max slide for properties or display properties as a text box, all examples of built-in property drawers. In fact, we can define our own custom PropertyAttributes and state how they should draw associated properties in the inspector.
Presently we can hide properties using [HideInInspector], however what if we want to expose a property to the inspector but have it non-editable? As this is something that could be used throughout multiple classes and projects, one approach is to define a custom property attribute.
Firstly we define the property attribute itself:
/// <summary>An attribute to make a property non-editable (i.e. read only) in the inspector.</summary>
public sealed class ReadOnlyAttribute : PropertyAttribute {}
and then define how the property attribute should be drawn:
/// <summary>A custom property drawer for the ReadOnly attribute.</summary>
[CustomPropertyDrawer(typeof(ReadOnlyAttribute))]
public class ReadOnlyAttributeDrawer : PropertyDrawer
{
/// <summary>Callback to make a custom GUI for the property.</summary>
/// <param name="position">Rectangle on the screen to use for the property GUI..</param>
/// <param name="property">The SerializedProperty to make the custom GUI for..</param>
/// <param name="label">The label of this property..</param>
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
GUI.enabled = false;
EditorGUI.PropertyField(position, property, label, true);
GUI.enabled = true;
}
/// <summary>Callback to specify how tall the GUI for this field in pixels is. Default is 1 line high.</summary>
/// <returns>The height in pixels.</returns>
/// <param name="property">The SerializedProperty to make the custom GUI for..</param>
/// <param name="label">The label of this property..</param>
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
{
return EditorGUI.GetPropertyHeight(property, label, true);
}
}
This property attribute can then be easily used as follows:
public class MyComponent : MonoBehaviour
{
[Header("Health Settings")]
[SerializeField] private int currentHealth = 0;
[ReadOnly, SerializeField] private int maxHealth = 100;
}
Custom property attributes are a very powerful feature. To see their potential, take a look at this list of open-source property drawers.
Conclusion
By using Property Drawers we can customize how classes or properties are drawn in the inspector. As Property Drawers customize the look of all instances of a class/all properties with a specified attribute, they can easily be re-used throughout multiple classes and projects, thus potentially limiting the number of Custom Editors that need to be written.
Further Reading
50 Unity Tips - #15 Pimp the Inspector
50 Unity Tips - #17 Custom Editor
Forums - When to choose a custom editor vs. property drawer
This post was generated from a GitHub repository.