A Min-Max Range for Unity

Just another “I don’t know why I didn’t do this earlier” utility script, to get this:

MinMaxRange inspector

I’m tired of cluttering my code with this:

[code language=”csharp”]
public float minSpeed = 1;
public float maxSpeed = 5;

//…

void PickSpeed()
{
speed = Random.Range( minSpeed, maxSpeed );
}
[/code]

This doesn’t take a huge amount of effort to type out but it means you have to make sure min is always less than max, and there’s no easy way to define a range that the values can sit within. If an artist or anyone else is going to be setting this value through the inspector, these kind of limitations should be much clearer.

Unity includes code to make a Min-Max Range slider in the inspector, but (as far as I can tell) doesn’t expose any easy way to use it, like it does for a simple single value range slider.

Using Property Drawers from Unity 4.x, I made a simple MinMaxRange class you can use to replace the min and max values in code with a custom class, and an attribute to use with it to define limits and show up as a slider in the inspector.

[code language=”csharp”]
/* MinMaxRangeAttribute.cs
* by Eddie Cameron – For the public domain
* —————————-
* Use a MinMaxRange class to replace twin float range values (eg: float minSpeed, maxSpeed; becomes MinMaxRange speed)
* Apply a [MinMaxRange( minLimit, maxLimit )] attribute to a MinMaxRange instance to control the limits and to show a
* slider in the inspector
*/

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class MinMaxRangeAttribute : PropertyAttribute
{
public float minLimit, maxLimit;

public MinMaxRangeAttribute( float minLimit, float maxLimit )
{
this.minLimit = minLimit;
this.maxLimit = maxLimit;
}
}

[System.Serializable]
public class MinMaxRange
{
public float rangeStart, rangeEnd;

public float GetRandomValue()
{
return Random.Range( rangeStart, rangeEnd );
}
}
[/code]

[code language=”csharp”]
/* MinMaxRangeDrawer.cs
* by Eddie Cameron – For the public domain
* ———————————————————–
* — EDITOR SCRIPT : Place in a subfolder named ‘Editor’ —
* ———————————————————–
* Renders a MinMaxRange field with a MinMaxRangeAttribute as a slider in the inspector
* Can slide either end of the slider to set ends of range
* Can slide whole slider to move whole range
* Can enter exact range values into the From: and To: inspector fields
*
*/

using UnityEngine;
using UnityEditor;
using System.Collections;
using System.Collections.Generic;

[CustomPropertyDrawer( typeof( MinMaxRangeAttribute ) )]
public class MinMaxRangeDrawer : PropertyDrawer
{
public override float GetPropertyHeight( SerializedProperty property, GUIContent label )
{
return base.GetPropertyHeight( property, label ) + 16;
}

// Draw the property inside the given rect
public override void OnGUI( Rect position, SerializedProperty property, GUIContent label )
{
// Now draw the property as a Slider or an IntSlider based on whether it’s a float or integer.
if ( property.type != "MinMaxRange" )
Debug.LogWarning( "Use only with MinMaxRange type" );
else
{
var range = attribute as MinMaxRangeAttribute;
var minValue = property.FindPropertyRelative( "rangeStart" );
var maxValue = property.FindPropertyRelative( "rangeEnd" );
var newMin = minValue.floatValue;
var newMax = maxValue.floatValue;

var xDivision = position.width * 0.33f;
var yDivision = position.height * 0.5f;
EditorGUI.LabelField( new Rect( position.x, position.y, xDivision, yDivision )
, label );

EditorGUI.LabelField( new Rect( position.x, position.y + yDivision, position.width, yDivision )
, range.minLimit.ToString( "0.##" ) );
EditorGUI.LabelField( new Rect( position.x + position.width – 28f, position.y + yDivision, position.width, yDivision )
, range.maxLimit.ToString( "0.##" ) );
EditorGUI.MinMaxSlider( new Rect( position.x + 24f, position.y + yDivision, position.width – 48f, yDivision )
, ref newMin, ref newMax, range.minLimit, range.maxLimit );

EditorGUI.LabelField( new Rect( position.x + xDivision, position.y, xDivision, yDivision )
, "From: " );
newMin = Mathf.Clamp( EditorGUI.FloatField( new Rect( position.x + xDivision + 30, position.y, xDivision – 30, yDivision )
, newMin )
, range.minLimit, newMax );
EditorGUI.LabelField( new Rect( position.x + xDivision * 2f, position.y, xDivision, yDivision )
, "To: " );
newMax = Mathf.Clamp( EditorGUI.FloatField( new Rect( position.x + xDivision * 2f + 24, position.y, xDivision – 24, yDivision )
, newMax )
, newMin, range.maxLimit );

minValue.floatValue = newMin;
maxValue.floatValue = newMax;
}
}
}
[/code]

And…an example script showing use:
[code language=”csharp”]
/* Mover.cs
* by Eddie Cameron – For the public domain
* —————————-
* Example script using a MinMaxRange slider
*/

using UnityEngine;

public class Mover : MonoBehaviour
{
[MinMaxRange( 5f, 10f )]
// inspector slider can move between these values
public MinMaxRange
speed;

float randomSpeed;

void Start()
{
randomSpeed = speed.GetRandomValue();
// can access range directly with speed.rangeStart and speed.rangeEnd
}

void Update()
{
transform.Translate( Vector3.forward * randomSpeed );
}
}
[/code]

Screen Shot 2013-11-24 at 1.12.25 pm