Author Topic: Improvement Suggestions for UIProgressBar & UISlider  (Read 3903 times)

DCalabrese

  • Newbie
  • *
  • Thank You
  • -Given: 2
  • -Receive: 0
  • Posts: 23
    • View Profile
Improvement Suggestions for UIProgressBar & UISlider
« on: May 23, 2015, 04:55:24 PM »
Found some interesting conditions regarding UIProgressBar. Had to make some changes to the UIProgressBar.cs script that I would like to share here, as I think they could be valid updates to it overall.

Silent Value Changing
In our project we have various UISliders (which are derived from UIProgressBar). The values are changed by the player, then saved. When the player returns to that dialog, the sliders need to be the same value where they were left. We ran into issues where we would change the value of the progress bar in script, and since the value changed - the OnChange event would get toggled. This led to some various ugly situations. The best answer we found was to add a method to UIProgressBar which would allow changing the value property, without toggling the OnChange event. That code is as follows. It's pretty much the same as the value property, only does not call the event.

  1.         /// <summary>
  2.         /// Changes the value without toggling the callback. Use for when changing the value in script
  3.         /// </summary>
  4.         /// <param name="newValue">New value to be saved to mValue.</param>
  5.         public void changeValueNoCallback(float newValue)
  6.         {
  7.                 float val = Mathf.Clamp01(newValue);
  8.                 if (mValue != val)
  9.                 {
  10.                         float before = this.value;
  11.                         mValue = val;
  12.                        
  13.                         if (before != this.value)
  14.                                 ForceUpdate();
  15.  
  16.                         #if UNITY_EDITOR
  17.                         if (!Application.isPlaying)
  18.                                 NGUITools.SetDirty(this);
  19.                         #endif
  20.                 }
  21.         }
  22.  


Misplaced Object Creation Event Calls
Next, we found another issue where every time the dialog opened, regardless of us setting the value to what we wanted, it would be automatically changed to whatever we defaulted the value to in the editor. This was tracked down to the OnChange event delegate being called as soon as the dialog was opened. That can be fixed by simply removing those lines of code. This also isn't needed, because the UIProgressBar was just displayed - the value isn't changed by the user, therefore calling the EventDelagate in this case causes far more problems than it helps with. To address that, just change the Start method in UIProgressBar to the following:

  1.         protected void Start ()
  2.         {
  3.                 Upgrade();
  4.  
  5.                 if (Application.isPlaying)
  6.                 {
  7.                         if (mBG != null) mBG.autoResizeBoxCollider = true;
  8.  
  9.                         OnStart();
  10.  
  11.                         // Comment out or remove the following block of code to prevent the event from running.
  12.                         /*if (current == null && onChange != null)
  13.                         {
  14.                                 current = this;
  15.                                 EventDelegate.Execute(onChange);
  16.                                 current = null;
  17.                         }*/
  18.                 }
  19.                 ForceUpdate();
  20.         }
  21.  

Hopefully those help out some people stuck with other similar oddities when working with UIProgressBar and UISlider!

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: Improvement Suggestions for UIProgressBar & UISlider
« Reply #1 on: May 26, 2015, 02:53:13 PM »
The callback is meant to be called whenever value is changed/set. Whatever the callback is supposed to do needs to be in the same exact state as the slider. Take the example where you get a script that has an Awake() function that reads some saved values, say PlayerPrefs and sets the value of the slider. The slider's OnChange is linked to a label that displays the value. If you get rid of the part that sets the value on start, when you run into a situation where the slider will show one value, while the label will show another.

I suggest you re-examine your code to see why callback being called is a problem for you.

DCalabrese

  • Newbie
  • *
  • Thank You
  • -Given: 2
  • -Receive: 0
  • Posts: 23
    • View Profile
Re: Improvement Suggestions for UIProgressBar & UISlider
« Reply #2 on: May 26, 2015, 03:44:51 PM »
Yes, and I agree that would be the best way - but it doesn't seem to work right as there is a race condition. Once the dialog is opened, NGUI populates the field with its default value. Our code is then setting the .value of the slider. The two collide, and the default value ends up taking control. Since it also toggles the script, the value saved for the game ends up getting set to the default value. The obvious question here is - why not just wait a moment and then set our value? The reason for that is the visual display. NGUI waits until the object is entirely enabled - then it sets the default value. So if we wait for the default value to be set before giving it our value, the user will see a noticeable pop of one value, which then jumps to another value.

So another fix for this would be to have the slider have an option to not set its default value upon enable.

jrhee

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 2
  • Posts: 13
    • View Profile
Re: Improvement Suggestions for UIProgressBar & UISlider
« Reply #3 on: July 09, 2015, 12:13:43 PM »
Hi,

Sorry to necro this- I'm a bit confused on this one as well. Here's my problem code:

  1. // called in ConfigManager.Start()
  2. void LoadConfig()
  3. {
  4.         Display.Brightness = savedBrightnessValue;
  5. }
  6.  
  7. // in myBrightnessSlider OnValueChange
  8. void OnBrightnessSliderChanged()
  9. {
  10.         Display.Brightness = UISlider.current.value;
  11. }
  12.  

The sequence:
Config.Start() is called - display.brightness is set
OnValueChanged delegate invoked via UIProgressBar.Start() - display.brightness is set again to default slider value

What's the recommended practice here?

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: Improvement Suggestions for UIProgressBar & UISlider
« Reply #4 on: July 12, 2015, 07:54:22 PM »
Set your Display.Brightness in Awake().