Slider.Rebuild invokes OnValueChanged?

So when first starting the app, it’s calling OnValueChanged on all the Sliders.

When I look at what’s causing this, it’s:

Canvas.SendWillRenderCanvases
CanvasUpdateRegistry.PerformUpdate
Slider.Rebuild
UnityEvent.Invoke

This is not what I want. Especially because when you change the value it saves to the PlayerPrefs. But this is getting called before the old PlayerPrefs are loaded from the previous session.

So is there a way to distinguish in the function getting called from the OnValueChanged, whether it was called from Slider.Rebuild and not from an actual user input?

2 Likes

Bumping this because I’ve apparently run into the exact same problem and my old thread is the only thing I found when I searched for it.

I think I resorted to a workaround last time, where I added another variable to keep track whether the value has been loaded from player prefs yet.

But it kind of bothers me on principle that OnValueChanged is Invoked by Rendering the Canvas? How does that make sense?

2 Likes

Run into this exact same issue… I assume that the best solution is to add a flag as you said

Edit: Could it be that this strange behaviour only happens when you put play while editing the prefab with the slider?

1 Like

Faced with the same problem. As a workaround I’ve created this script:

    [RequireComponent(typeof(Slider))]
    public class SliderListenerWorkaround : MonoBehaviour
    {
        [SerializeField] private ValueEvent _onValueChanged = new ValueEvent();

        private Slider slider => GetComponent<Slider>();

        private void OnEnable() => slider.onValueChanged.AddListener(_onValueChanged.Invoke);
        private void OnDisable() => slider.onValueChanged.RemoveListener(_onValueChanged.Invoke);

        [Serializable] private class ValueEvent : UnityEvent<float>{}
    }

Yes. I have the same bug, and it seems that the slider calling OnValueChanged is not the instance that is in the game, but the one that is open in the prefab edition. Even if OnValueChanged is configured on “Runtime Only”, so this is clearly a bug.

My workaround is something like this :

public class PopUpMenu : MonoBehavior
{
    void Start()
    {
        _instance = this;
    }

    // Called by OnValueChanged
    public void SetGlobalVolume() {
         if(  _instance == this )
            SoundManager.GetInstance().SetGlobalVolume( _globalVolume.value ); // Do the stuff only if this is the last instance created.
}

    static public PopUpMenu _instance;
}