What is the best way of persisting UI element settings to PlayerPrefs? It’s easy enough to save a slider value as soon as it changes, e.g.:
public function SetMasterVolume (volume : float) {
AudioListener.volume = volume;
PlayerPrefs.SetFloat("MasterVolume", volume);
Debug.Log("MASTER VOLUME SET TO " + volume);
}
Restoring the value at startup seems straightforward too:
public var masterVolumeSlider : Slider;
function Start () {
var vol : Float = PlayerPrefs.GetFloat("MasterVolume", 1.0);
masterVolumeSlider.value = vol;
Debug.Log("MASTER VOLUME IS " + vol);
}
However, if you run the above code, you will see that the event system will set the master volume to 1.0 (the value of the slider in the Editor UI). It will do this not once, but four (4) times at startup, which clearly is both redundant and wasteful, thus overwriting the persisted value and setting it to 1.0 in the process.
The event system also calls the SetMasterVolume function from the Editor with the value 1.0 when execution stops, again meaning that any persisted value will be overwritten with 1.0, the value of the slider in the Editor UI.
How can I avoid this and persist the real, useful, user-modified slider value only?
No persistence in Unity should ever be automated outside of the editor: Unity’s strength is that it is a giant box of legos that you can put together any way you want that doesn’t try to force you into its mould.
That question is really beside the point. The problem here is that the UI event system and/or the Editor, are firing OnChange events at points where it really shouldn’t or at least where it’s undocumented, and multiple times to boot and in cases where there is no actual change. My question primarily has to do with how to avoid this automatic behaviour: there might be state information to examine, for instance, or recommended best practices. I’ve been using Unity since 2010, so I’m very familiar with the engine.
The problem can be solved in the most recent 4.6 beta (18) in the following way:
#pragma strict
import UnityEngine.UI;
public var masterVolumeSlider : Slider;
private var readonly : boolean = true;
function Start () {
masterVolumeSlider.value = PlayerPrefs.GetFloat("MasterVolume", 1.0);
readonly = false;
}
public function SetMasterVolume (volume : float) {
AudioListener.volume = volume;
if (readonly) return;
PlayerPrefs.SetFloat("MasterVolume", volume);
}
Feels like a kludge though. The newest beta only fires the OnChange event twice, though, during the Awake phase. Those events are still redundant, as far as I can see.