Vector2RangeAttribute Featured

Unity Tutorial: Vector2RangeAttribute

In my previous Unity tutorial, we created a parallax / holographic card. One of the settings of the ParallaxPanelScript was a Vector2 property, that controls the maximum rotation of the card, which we’d like to limit to a [0, 50] range for each axis. However, Unity’s regular RangeAttribute does not support Vector2 types. In this post, we’ll create a custom Unity PropertyAttribute along with a matching Unity PropertyDrawer, to support Vector2 range.

Let’s create our own RangeAttribute

Let’s create our own RangeAttribute for Vector2Vector2RangeAttribute, and add a custom PropertyDrawer for it:

public class Vector2RangeAttribute : PropertyAttribute
{
    // Min/Max values for the X axis
    public readonly float MinX;
    public readonly float MaxX;
    // Min/Max values for the Y axis
    public readonly float MinY;
    public readonly float MaxY;

    public Vector2RangeAttribute(float fMinX, float fMaxX, float fMinY, float fMaxY)
    {
        MinX = fMinX;
        MaxX = fMaxX;
        MinY = fMinY;
        MaxY = fMaxY;
    }
}

Now, we can use our Vector2RangeAttribute on the Vector2 property:

[Vector2Range(0, 50, 0, 50, true)]
public Vector2 maxRotation;

Now, to the PropertyDrawer

The attribute on its own won’t give us much. We need a PropertyDrawer class (placed inside the special Editor folder), that will control the display of the property in the Unity Inspector:

[CustomPropertyDrawer(typeof(Vector2RangeAttribute))]
public class Vector2RangeAttributeDrawer : PropertyDrawer
{
	public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
	{
		EditorGUI.BeginChangeCheck();
		// Create a regular Vector2 field
		Vector2 val = EditorGUI.Vector2Field(position, label, property.vector2Value);
		// If the value changed
		if (EditorGUI.EndChangeCheck())
		{
			var rangeAttribute = (Vector2RangeAttribute)attribute;
			// Clamp the X/Y values to be within the allowed range
			val.x = Mathf.Clamp(val.x, rangeAttribute.MinX, rangeAttribute.MaxX);
			val.y = Mathf.Clamp(val.y, rangeAttribute.MinY, rangeAttribute.MaxY);
			// Update the value of the property to the clampped value
			property.vector2Value = val;
		}
	}
}

Now, we can limit the values of our Vector2 properties on each axis separately. Needless to say, we can expand our attribute to support Vector3 and Vector4, as well as Vector2Int and Vector3Int. For that matter, we can use the same technic for Rect, Bounds and any other type we’d like.

GET NOTIFIED

Sign up to receive notifications when a new Unity Asset is released.