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.