Can You change the value of a toggle without having it call it’s OnValueChanged functions?
When the user presses the toggle i need some code to happen but sometimes i need to change the Active state of the toggle in code without triggering it’s OnValueChanged. Is there a way to “silently” switch the state of a toggle?
It would be super helpful, I’m converting some of our old UI to the new system and I noticed that we would have some potential infinite loops if we used the OnValueChanged for a lot of things.
Its pretty problematic whenever you are using one of the new UI elements to represent another piece of data that can change from something that isn’t direct user input.
For example if I have int X and I make a slider so the user can change the value of int x. I would make the slider’s OnValueChanged change the value of X. Then if for some reason the value X changes because of some other code I have to update the value of the slider so it accurately reflects the new value of X. Setting the value of the slider in code to the new value of X would trigger the sliders OnValueChanged which would set the value of X again.
If your OnValueChanged is doing more than just setting the value of something it can get pretty annoying.
Same problem here. I need to update a slider’s value based on a movie’s playback position. I would prefer not getting an OnValueChanged event when I change the slider’s value through code. Only when the user changes it by dragging the thumb, should the event be fired.
Another workaround that I just implemented is to instead of modifying the value that the slider represents, actually manipulate the slider instead. For instance, lets say you want a slider to represent music volume. But other things manipulate the volume as well (e.g. PlayerPrefs). Have them all go through the slider to change the volume, nothing changes the volume directly. The ONLY thing that accesses the volume is the slider, period. So it would go like this:
PlayerPrefs → Slider → Volume
Human → Slider → Volume
This basically means you cannot do a Model View Controller architecture using the new UI system without adding quite ugly code (I am currently writing said ugly code). If you cannot change a control’s state without triggering the entire UI logic, then the authoritative state is stored inside the UI control (so, the View), and not inside the Model.
I have player option data which is loaded from PlayerPrefs, and I need to set the player option UI to reflect that data. There is no way around this, and every game with any kind of options must surely do this, and run into this exact same problem.
When I set the UI control’s state, that forcibly triggers the same logic as if the player had clicked on it. Which in my case means that initializing the player option UI does the same thing as if the player clicks every single control, which is problematic in my case.
I now have to implement “React to this button except when this flag says we’re initializing the UI” logic. The solution by Daniel above could work too, but it has its own drawbacks.
I have a similar problem with the new UI. Working on an RTS-like game and want UI toggles to represent the states of units when they get selected. I wondered if there was a decent way to (re)set UI elements without triggering any functions.
The thing that baffles me is if you look at the source for Toggle, in the (private) Set function that takes an argument dictating whether or not to send the callback, it does an early out if the value didn’t change. So I’m not sure why this infinite loop problem occurs in the first place.
Edit: Whoops, never mind. I see why that wouldn’t solve the problem.
In this case, I don’t use the OnValueChanged methods.
Instead, I implement the interface IPointerClickHandler in the class and then I use the method: public void OnPointerClick(PointerEventData data)
This method is called only when the user clicks on the toggle and not when the value is changed by code.