Created
August 31, 2025 12:00
-
-
Save khadzhynov/455779a8b2d1fb714140d8c68b922f98 to your computer and use it in GitHub Desktop.
RandomRange - inspector helper
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| using System; | |
| using UnityEngine; | |
| #if UNITY_EDITOR | |
| using UnityEditor; | |
| #endif | |
| namespace GG.Utils | |
| { | |
| /// <summary> | |
| /// A small helper to define a range of random values (int or float) in the inspector | |
| /// Property drawer included | |
| /// https://gist.github.com/khadzhynov | |
| /// </summary> | |
| /// <typeparam name="T">Int or Float</typeparam> | |
| public abstract class RandomRange<T> where T : struct | |
| { | |
| protected abstract T GetMin(); | |
| protected abstract T GetMax(); | |
| private T? _cached; | |
| /// <summary> | |
| /// Each access will generate a new random value within the specified range. | |
| /// </summary> | |
| public T New => Random(GetMin(), GetMax()); | |
| /// <summary> | |
| /// Will generate and cache a new value on first access. | |
| /// Subsequent accesses will return the cached value. | |
| /// </summary> | |
| public T Cached => _cached ??= Random(GetMin(), GetMax()); | |
| public void ResetCache() => _cached = null; | |
| private static T Random(T min, T max) | |
| { | |
| if (typeof(T) == typeof(int)) | |
| return (T)(object)UnityEngine.Random.Range((int)(object)min, (int)(object)max); | |
| if (typeof(T) == typeof(float)) | |
| return (T)(object)UnityEngine.Random.Range((float)(object)min, (float)(object)max); | |
| throw new NotSupportedException(); | |
| } | |
| } | |
| [Serializable] | |
| public class RandomRangeFloat : RandomRange<float> | |
| { | |
| [SerializeField] private float _min, _max; | |
| protected override float GetMin() => _min; | |
| protected override float GetMax() => _max; | |
| } | |
| [Serializable] | |
| public class RandomRangeInt : RandomRange<int> | |
| { | |
| [SerializeField] private int _min, _max; | |
| protected override int GetMin() => _min; | |
| protected override int GetMax() => _max; | |
| } | |
| #if UNITY_EDITOR | |
| [CustomPropertyDrawer(typeof(RandomRangeFloat))] | |
| [CustomPropertyDrawer(typeof(RandomRangeInt))] | |
| public sealed class RandomRangeFloatDrawer : PropertyDrawer | |
| { | |
| public override float GetPropertyHeight(SerializedProperty property, GUIContent label) | |
| => EditorGUIUtility.singleLineHeight; | |
| public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) | |
| { | |
| EditorGUI.BeginProperty(position, label, property); | |
| var labelRect = new Rect(position.x, position.y, EditorGUIUtility.labelWidth, position.height); | |
| var fieldsRect = new Rect(position.x + EditorGUIUtility.labelWidth, position.y, | |
| position.width - EditorGUIUtility.labelWidth, position.height); | |
| EditorGUI.LabelField(labelRect, label); | |
| var minProp = property.FindPropertyRelative("_min"); | |
| var maxProp = property.FindPropertyRelative("_max"); | |
| if (minProp == null || maxProp == null) | |
| { | |
| EditorGUI.LabelField(fieldsRect, "Expected _min and _max"); | |
| EditorGUI.EndProperty(); | |
| return; | |
| } | |
| const float spacing = 4f; | |
| float half = (fieldsRect.width - spacing) * 0.5f; | |
| var minRect = new Rect(fieldsRect.x, fieldsRect.y, half, fieldsRect.height); | |
| var maxRect = new Rect(fieldsRect.x + half + spacing, fieldsRect.y, half, fieldsRect.height); | |
| float oldLabelWidth = EditorGUIUtility.labelWidth; | |
| EditorGUIUtility.labelWidth = 30f; | |
| EditorGUI.BeginChangeCheck(); | |
| if (minProp.propertyType == SerializedPropertyType.Integer) | |
| { | |
| SetIntProperty(minRect, minProp, maxRect, maxProp); | |
| } | |
| else if (minProp.propertyType == SerializedPropertyType.Float) | |
| { | |
| SetFloatProperty(minRect, minProp, maxRect, maxProp); | |
| } | |
| else | |
| { | |
| EditorGUI.EndChangeCheck(); | |
| EditorGUI.LabelField(fieldsRect, "Expected int or float."); | |
| } | |
| EditorGUIUtility.labelWidth = oldLabelWidth; | |
| EditorGUI.EndProperty(); | |
| } | |
| private static void SetFloatProperty(Rect minRect, SerializedProperty minProp, Rect maxRect, SerializedProperty maxProp) | |
| { | |
| float min = EditorGUI.FloatField(minRect, "Min", minProp.floatValue); | |
| float max = EditorGUI.FloatField(maxRect, "Max", maxProp.floatValue); | |
| if (EditorGUI.EndChangeCheck()) | |
| { | |
| if (min > max) (min, max) = (max, min); | |
| minProp.floatValue = min; | |
| maxProp.floatValue = max; | |
| } | |
| } | |
| private static void SetIntProperty(Rect minRect, SerializedProperty minProp, Rect maxRect, SerializedProperty maxProp) | |
| { | |
| int min = EditorGUI.IntField(minRect, "Min", minProp.intValue); | |
| int max = EditorGUI.IntField(maxRect, "Max", maxProp.intValue); | |
| if (EditorGUI.EndChangeCheck()) | |
| { | |
| if (min > max) (min, max) = (max, min); | |
| minProp.intValue = min; | |
| maxProp.intValue = max; | |
| } | |
| } | |
| } | |
| #endif | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| using UnityEngine; | |
| namespace GG.Utils | |
| { | |
| public class RandomRangeDemo : MonoBehaviour | |
| { | |
| [SerializeField] private RandomRangeInt _testInt; | |
| [SerializeField] private RandomRangeFloat _testFloat; | |
| private void Start() | |
| { | |
| Debug.Log( | |
| $"Test <_testInt>; calling [New] 4 times: {_testInt.New}, {_testInt.New}, {_testInt.New}, {_testInt.New}; " + | |
| $"\ncalling [Cached] 4 times: {_testInt.Cached}, {_testInt.Cached}, {_testInt.Cached}, {_testInt.Cached}"); | |
| _testInt.ResetCache(); | |
| Debug.Log($"Cache reset - call [Cached] again 4 more times: {_testInt.Cached}, {_testInt.Cached}, {_testInt.Cached}, {_testInt.Cached}"); | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment