- Home /
UI Slider; -x to +x range, 0 center; how can I get it to fill both directions starting from center?
Situation:
I have a slider, with default value 0, and a range that goes from -5 to +5, with "whole numbers" checked; the slider is in it's default horizontal position.
When the slider is at zero, half of it will always be filled (using either l to r, or r to l direction). This is what I am trying to get around.
I would like for it to have 0% fill at 0, and to either go left or right depending on whether its handle is dragged to a positive or negative value.
And now for a rudimentary ASCII example:
For value +3, whitespace is no fill, - is fill, # is a notch in the whole number slider
-5 0--- 5
Instead of:
-5----0--- 5
Or:
-5 0 --5
Anyways... I'm not really sure where to start, would love to hear your suggestions!
Thanks
PS: C# preferred... but I suppose beggars can't be choosers :)
I'm taking a wild guess in the dark here, but, could you not solve this by scaling the slider bar? Start it at 0 x scaling, and as it's dragged in a direction, scale it based on the slider value.
This is pretty similar to how I've handled health bars before. You just need to know your constant "max" values. (example: 5 = 100% positive x scale, 0 = 0% x scale, -5 = -100% x scale.
Answer by Veldars · Jul 10, 2015 at 01:27 PM
Hi, I wrote this script, that you can apply on a Slider... I use it to do that :
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
[RequireComponent (typeof(Slider))]
[RequireComponent (typeof(RectTransform))]
public class SliderSwitcher : MonoBehaviour {
private Slider _slider;
private float _sliderSize;
void Awake() {
_slider = GetComponent<Slider> ();
}
void Update() {
UpdateSliderSense ();
}
public void UpdateSliderSense() {
if (_sliderSize == 0) {
_sliderSize = GetComponent<RectTransform> ().rect.width;
_sliderSize = _sliderSize / (_slider.maxValue - _slider.minValue);
}
_slider.fillRect.rotation = new Quaternion (0,0,0,0);
_slider.fillRect.pivot = new Vector2 (_slider.fillRect.transform.parent.localPosition.x, _slider.fillRect.pivot.y);
if (_slider.value > 0) {
_slider.fillRect.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, _sliderSize * _slider.value);
} else {
_slider.fillRect.Rotate(0, 0, 180);
_slider.fillRect.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, -1 * _sliderSize * _slider.value);
}
_slider.fillRect.localPosition = new Vector3 (0, 0, 0);
}
}
I hope this help.
Answer by Eloujah · Jul 26, 2020 at 04:22 AM
And here is an even better refact!
using UnityEngine;
using UnityEngine.UI;
[RequireComponent(typeof(Slider))]
public class SliderSwitcher : MonoBehaviour
{
private Slider _slider;
private float center = 0.5f;
void Awake() {
_slider = GetComponent<Slider>();
}
void Update() {
_slider.fillRect.anchorMin = new Vector2(Mathf.Clamp(_slider.handleRect.anchorMin.x, 0, center), 0);
_slider.fillRect.anchorMax = new Vector2(Mathf.Clamp(_slider.handleRect.anchorMin.x, center, 1), 1);
}
}
Answer by Eloujah · Jul 26, 2020 at 04:19 AM
If anyone is still looking for this kind of slider behaviour. Here is a simplier version of the script:
using UnityEngine;
using UnityEngine.UI;
[RequireComponent(typeof(Slider))]
public class SliderSwitcher : MonoBehaviour
{
private Slider _slider;
void Awake() {
_slider = GetComponent<Slider>();
}
void Update() {
UpdateSliderSense();
}
public void UpdateSliderSense() {
if (_slider.value > 0) {
_slider.fillRect.anchorMin = new Vector2(0.5f, 0);
_slider.fillRect.anchorMax = new Vector2(_slider.handleRect.anchorMin.x, 1);
} else {
_slider.fillRect.anchorMin = new Vector2(_slider.handleRect.anchorMin.x, 0);
_slider.fillRect.anchorMax = new Vector2(0.5f, 1);
}
}
}