Anyone know of a way to make the new Slider bar allow for step intervals? I want to have a quality slider That allows for 5 different settings.
On the Slider you have Min Value, Max Value, a bool for Whole Numbers, and a Value. if you want 6 steps on the slider just set Min Value to 0, Max Value to 5, and check Whole Numbers. If you would rather start at 1 then set them to 1 and 6 respectively.
Thanks for digging out a 3.5 years old thread Your example covers 100 steps. so make the bar from 0 to 100 and multiply the value with 10 in your code.
Digging a 4.5 year old thread wouldn't be a problem if Unity wasn't daft enough to delete Unity Answers.
Hey! This is a simple code to help you guys out! You'll have to attach this script to your slider component, then hook the UpdateStep() function to the OnValueChanged event in the Editor. Hope it helps! Code (CSharp): public class UISliderStep : MonoBehaviour { int stepAmount = 100; Slider mySlider = null; int numberOfSteps = 0; // Start is called before the first frame update void Start() { mySlider = GetComponent<Slider>(); numberOfSteps = (int) mySlider.maxValue / stepAmount; } public void UpdateStep() { float range = (mySlider.value / mySlider.maxValue) * numberOfSteps; int ceil = Mathf.CeilToInt(range); mySlider.value = ceil * stepAmount; } }
I just added the method below to Slider's list of events and then divide the max value of the slider by 5 accordingly. e.g for values from 0 to180. min is set to 0, max is set to 36. public void SetSliderAmount(float _value) { someFloat = (int)(_value * 5); }
I know there must be better answers for the question but after encountering with this page several times and trying my own, i finally went this way, sorry for necromancing the page again in 2022, hope it helps somebody: public Slider mySlider; public float step; public void SliderClamp() { for (float i = mouseSlider.minValue; i <= mouseSlider.value; i += step) { if(mySlider.value < i && mySlider.value > i-step) mySlider.value = i; else if (mySlider.value > i && mySlider.value < i+step) mySlider.value = i+step; } } Attaching the slider in the inspector and calling the method on value change will clamp the value to the nearest step possible (Works for me with min/max values set to 0.5/4.5 and step to 0.2)
The basic calculation required to limit a Slider value to discrete steps is no more than this: Code (CSharp): float steppedValue = Mathf.Round(slider.value / StepSize) * StepSize; Below my class that wraps that makes this a convenient component. Simply save it as UISliderStep.cs and add it to the Slider component, then set your value for Step Size. The class registers a lister for changes to the Slider and updates it with the desired stepped value. When running in the editor, the class will also complain if the value for Step Size is too large to make sense. Cheers! Code (CSharp): using UnityEngine; using UnityEngine.UI; /// <summary> /// Attach this script to a Unity.UI Slider component to control the step size within the slider range. /// </summary> [RequireComponent(typeof(Slider))] public class UiSliderStep : MonoBehaviour { [Tooltip("The desired difference between neighbouring values of the Slider component.")] [MinAttribute(0.0001f)] public float StepSize = 0.0001f; private Slider _slider; void Start() { _slider = GetComponent<Slider>(); if (_slider != null) { _slider.onValueChanged.AddListener(ClampSliderValue); } } /// <summary> /// Calculates the nearest stepped value and updates the Slider component. /// </summary> /// <param name="value">Current slider value</param> public void ClampSliderValue(float value) { if (_slider != null && StepSize > 0) { float steppedValue = Mathf.Round(value / StepSize) * StepSize; if (steppedValue != value) { _slider.value = steppedValue; Debug.Log(string.Format("New stepped Slider value: {0}", _slider.value)); } #if UNITY_EDITOR // Help find non-sensical values during development. Gets stripped out for platform build. int _numberOfSteps = (int)((_slider.maxValue - _slider.minValue) / StepSize); if (_numberOfSteps < 1 || steppedValue < _slider.minValue || steppedValue > _slider.maxValue) { Debug.LogWarning(string.Format("StepSize is too large. Consider reducing StepSize to less than {0}.", _slider.maxValue - _slider.minValue)); } #endif } } }
Hi old thread! Thanks for solutions but why did Unity not think to add a step option - either number of steps or step size (float), while keeping the min/max values to what you actually want to get out of it?! Hoping better design in next UI
My little solution use at your own risk Code (CSharp): using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.UI; public class SliderSmooth : Slider { [SerializeField] float steps = 100f; //smoothed steps float horizontalAxis; float verticalAxis; float holdTime; float lastPressTime; protected override void Update() { if (!wholeNumbers) { if (IsVertical()) { verticalAxis = Input.GetAxis("Vertical"); UpdateSliderValue(verticalAxis); } else { horizontalAxis = Input.GetAxis("Horizontal"); UpdateSliderValue(horizontalAxis); } } base.Update(); } public bool IsVertical() { return (direction == Direction.BottomToTop || direction == Direction.TopToBottom); } public override void OnMove(AxisEventData eventData) { if (IsVertical()) { if (wholeNumbers) { UpdateSliderValue(verticalAxis); } if (verticalAxis != 0) { return; } } else { if (wholeNumbers) { UpdateSliderValue(horizontalAxis); } if (horizontalAxis != 0) { return; } } base.OnMove(eventData); } public void UpdateSliderValue(float axis) { if (axis != 0) { CheckAndSetLastTime(); SliderUpdate(axis); } else { ResetHoldTime(); } } public void ResetHoldTime() { lastPressTime = 0; holdTime = 0; } public void CheckAndSetLastTime() { if (lastPressTime == 0) { lastPressTime = Time.time; } holdTime = Time.time - lastPressTime; } public void SliderUpdate(float inputAxis) { //inverse if (direction == Direction.TopToBottom || direction == Direction.RightToLeft) { inputAxis = inputAxis*-1; } if (wholeNumbers) { value = value + Mathf.Round(inputAxis); } else { float range = maxValue - minValue; value = value + ((range * holdTime) / steps) * inputAxis; } } }