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 Vector2 – Vector2RangeAttribute, 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.