Search Unity

Unity's Toggle calls function on game exit

Discussion in 'Scripting' started by deLord, Aug 18, 2017.

  1. deLord

    deLord

    Joined:
    Oct 11, 2014
    Posts:
    306
    Hey there

    I use a Toggle Component to toggle music on/off. I want to save the PlayerPrefs of course but when I quit the Editor play mode, I can see in the debugger that the toggle function is being called which doesn't really make sense to me.

    SoundManager.toggleMuteSounds () in E:\mygame\Assets\scripts\SoundManager.cs:96
    UnityEngine.Events.InvokableCall.Invoke (args={object[1]}) in C:\buildslave\unity\build\Runtime\Export\UnityEvent.cs:153
    UnityEngine.Events.InvokableCallList.Invoke (parameters={object[1]}) in C:\buildslave\unity\build\Runtime\Export\UnityEvent.cs:634
    UnityEngine.Events.UnityEventBase.Invoke (parameters={object[1]}) in C:\buildslave\unity\build\Runtime\Export\UnityEvent.cs:769
    UnityEngine.Events.UnityEvent<bool>.Invoke (arg0=true) in C:\buildslave\unity\build\Runtime\Export\UnityEvent_1.cs:53
    UnityEngine.UI.Toggle.Rebuild (executing=UnityEngine.UI.CanvasUpdate.Prelayout) in C:\buildslave\unity\build\Extensions\guisystem\UnityEngine.UI\UI\Core\Toggle.cs:85
    UnityEngine.UI.CanvasUpdateRegistry.PerformUpdate () in C:\buildslave\unity\build\Extensions\guisystem\UnityEngine.UI\UI\Core\CanvasUpdateRegistry.cs:122
    UnityEngine.Canvas.SendWillRenderCanvases () in C:\buildslave\unity\build\artifacts\generated\common\modules\UI\UICanvasBindings.gen.cs:206

    My current code (only called when I stop the Play mode) looks like this
    Code (CSharp):
    1.     public void toggleMuteMusic(){
    2.         masterMixer.SetFloat("musicVol", -80f);
    3.         PlayerPrefs.SetFloat("musicVol", -80f);
    4.         if(musicVolSlider.interactable){
    5.             masterMixer.SetFloat("musicVol", musicVolSlider.value);
    6.             PlayerPrefs.SetFloat("musicVol", musicVolSlider.value);
    7.         }
    8.         musicVolSlider.interactable = !musicVolSlider.interactable;
    9.     }
    Although I put PlayerPrefs.Save() into a different function ONLY to be called by a GUI button, when I start the game the second time withouth doing anything else, the vol will be what the inscene slider values are set to (-10). The moment I quit the game, the registry entry will be set (why??). It seems it has to do with the initial value of the slider and enabled/disabled objects. If I add another variable called muteMusic and start the game, even this will be set to true because for some reason, the Toggle function is being called the moment I quit the game. This doesnt make sense.
    My PlayerPrefs are saved even if I never clicked the button that calls the Save() function.

    Initial slider value is -10, script loads -11 if no PlayerPrefs are found. First start it loads -11, then I quit without doing anything, next times it loads -10 although this value was never Save()d.

    Does anyone have any ideas how to circumvent this and what exactly is happening here?
     
    Last edited: Aug 18, 2017
  2. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,334
    Unity's UI code is open source, so you can actually check what's going on.

    It's clear that this is intended, in the editor only. The code for Toggle's .Rebuild is this:

    Code (csharp):
    1.  
    2.        public virtual void Rebuild(CanvasUpdate executing)
    3.         {
    4. #if UNITY_EDITOR
    5.             if (executing == CanvasUpdate.Prelayout)
    6.                 onValueChanged.Invoke(m_IsOn);
    7. #endif
    8.         }
    9.  
    So "if we're getting rebuilt due to a Prelayout update in the editor, call onValueChanged with the current state".

    I have no idea why that would make sense. It might be to support the (somewhat insane) feature where UnityEvents can be set to "Editor and Runtime", but since you can't interact with Toggles in edit mode, I have no idea what it's supposed to do.


    The UI has a bunch of these strange and confusing things in it. The code quality is quite low. What's nice, though, is that for once in Unity-land everything's not sealed, so you can simply inherit from Toggle and override Rebuild to not be crazy.
     
  3. deLord

    deLord

    Joined:
    Oct 11, 2014
    Posts:
    306
    Thank you, this explains one part of my question.

    The other one remains though: why is PlayerPrefs.Save() called although I never clicked the button that is supposed to do that?