- Home /
C# How To Save PlayerPrefs for Unity GUI
I want to save values within Unity's GUI. Except I'm not entirely sure how to retrieve the variables. For instance look at this function below.
public void sliderText (Slider s) {
Text t = s.GetComponentInChildren<Text>();
t.text = s.value.ToString();
}
It references a slider variable and a text variable. But those variables are confined within the function. So the only means of retrieving the variables are either putting a playerprefs function directly into the GUI function or declaring the variable you want to save in the script. The former would be fine if I didn't want to interact with the slider in order to save it. I want to tie saving it to an apply button which uses a different function. In the later case why even bother assigning the GUI function when you declare them as a variable? I had considered calling the variable by name and assigning them to the GUI's value. Except you would need a means of assigning them on awake for the playerprefs which as far as I'm aware that can only be done by declaring a variable and assigning it in the awake function. Is there something that I'm missing that could help me save the GUI functions variables?
Answer by Statement · Oct 08, 2015 at 08:27 PM
Um, not really sure what you're asking.
But this is one way to do it, by having a dedicated class to deal with all the settings you need to save and handle the backing end there. Then have a script component which just routes data between the UI components and the user settings. Of course you can get more clever about it, but this is about as easy as it gets.
I have no idea why you were trying to shoehorn it into a piece of code where you were updating textual representation of a slider.
public class UserSettingsUI : MonoBehaviour
{
// Assume these have been set properly...
public Slider volumeSlider;
public Slider fooSlider;
public Slider barSlider;
void Awake()
{
// Load settings into UI at awake...
UserSettings.Load();
volumeSlider.value = UserSettings.Volume;
fooSlider.value = UserSettings.Foo;
barSlider.value = UserSettings.Bar;
}
void Apply()
{
// Save the settings so they are stored when we are done with them.
UserSettings.Volume = volumeSlider.value;
UserSettings.Foo = fooSlider.value;
UserSettings.Bar = barSlider.value;
UserSettings.Save();
}
}
public static class UserSettings
{
public static float Volume;
public static float Foo;
public static float Bar;
public static void Load()
{
Volume = PlayerPrefs.GetFloat("Volume", 0.5f);
Foo = PlayerPrefs.GetFloat("Foo");
Bar = PlayerPrefs.GetFloat("Bar");
}
public static void Save()
{
PlayerPrefs.SetFloat("Volume", Volume);
PlayerPrefs.SetFloat("Foo", Foo);
PlayerPrefs.SetFloat("Bar", Bar);
PlayerPrefs.Save();
}
}
A slightly different approach which immediately makes changes to the backing store could look similar to this. Note that there is no way to discard or "not apply" your changes this way - you'd have to write more code to support it. With the previous solution you could just call UserSettings.Load() to discard unsaved changes.
public static class UserSettings
{
public static float Volume
{
get { return PlayerPrefs.GetFloat("Volume", 0.5f); }
set { PlayerPrefs.SetFloat("Volume", value); }
}
public static float Foo
{
get { return PlayerPrefs.GetFloat("Foo"); }
set { PlayerPrefs.SetFloat("Foo", value); }
}
public static float Bar
{
get { return PlayerPrefs.GetFloat("Bar"); }
set { PlayerPrefs.SetFloat("Bar", value); }
}
public static void Save()
{
PlayerPrefs.Save();
}
}
Although I don't really know if I am hitting the head of your nail here. If I missed, please try to be more concrete about what your problem is.
That's what I'm trying to avoid doing. I don't want to declare all of my controls in a script. It defeats the point of declaring the variable in the GUI's function.
$$anonymous$$y problem is with the way Unity's GUI System executes. in order to change a GUI value like a slider's value you have to declare that variable in the function's parameters. Now how do you save that variable with playerprefs? It isn't a persistent variable like a declared variable in a script.
public slider s;// Only refers to one variable. Is persistent
public void sliderText (Slider s) { // can refer to multiple variables. Is not persistent
}
Answer by Statement · Oct 09, 2015 at 06:10 PM
Here's one example with two settings that are driven by sliders and stored in PlayerPrefs. This way you don't need to define all of your controllers in scripts and instead you can use components to model your menu accordingly.
The UserSetting component loads the setting from PlayerPrefs, using the key which you set in the inspector. Then it fires an event that the setting has been loaded, which is routed to Slider.value for that setting. This updates the UI. The slider also sends an event to PercentText component which formats the percentual text representation on the right side of the slider. When the slider is interacted with, both the text and the setting is updated. Lastly there are two buttons to apply (save) the changes to playerprefs or discard (load) them to the previously applied settings.
This approach is modular, although I am not the kind of guy who like to set up references via the inspector. To create a new setting for example, you'd basically duplicate one of the sliders, position it where you want it, change the key for the UserSetting component, rename the label and add an event to Apply and Discard to the new UserSettings Save and Load functions.
Of course, this could be code driven where you have a factory method for instantiating a copy of a prefab, setting the key and registering with the Apply and Discard buttons. I got bored so if you want to see one way of doing it, here's another package with code driving construction of the UI.