Search Unity

Question Slider.Rebuild invokes OnValueChanged?

Discussion in 'UGUI & TextMesh Pro' started by ryancampfire, Oct 20, 2020.

  1. ryancampfire

    ryancampfire

    Joined:
    Jan 4, 2017
    Posts:
    31
    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. ryancampfire

    ryancampfire

    Joined:
    Jan 4, 2017
    Posts:
    31
    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?
     
  3. FedericoCara

    FedericoCara

    Joined:
    Jan 5, 2016
    Posts:
    6
    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?
     
    Last edited: Apr 15, 2021
  4. unity_5D8553E10CBE24C8D4B1

    unity_5D8553E10CBE24C8D4B1

    Joined:
    Aug 10, 2021
    Posts:
    1
    Faced with the same problem. As a workaround I've created this script:
    Code (CSharp):
    1.  
    2.     [RequireComponent(typeof(Slider))]
    3.     public class SliderListenerWorkaround : MonoBehaviour
    4.     {
    5.         [SerializeField] private ValueEvent _onValueChanged = new ValueEvent();
    6.  
    7.         private Slider slider => GetComponent<Slider>();
    8.  
    9.         private void OnEnable() => slider.onValueChanged.AddListener(_onValueChanged.Invoke);
    10.         private void OnDisable() => slider.onValueChanged.RemoveListener(_onValueChanged.Invoke);
    11.  
    12.         [Serializable] private class ValueEvent : UnityEvent<float>{}
    13.     }
     
  5. GabrielWink

    GabrielWink

    Joined:
    Jun 30, 2018
    Posts:
    6
    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 :

    Code (CSharp):
    1. public class PopUpMenu : MonoBehavior
    2. {
    3.     void Start()
    4.     {
    5.         _instance = this;
    6.     }
    7.  
    8.     // Called by OnValueChanged
    9.     public void SetGlobalVolume() {
    10.          if(  _instance == this )
    11.             SoundManager.GetInstance().SetGlobalVolume( _globalVolume.value ); // Do the stuff only if this is the last instance created.
    12. }
    13.  
    14.     static public PopUpMenu _instance;
    15. }