0
Cannot Reproduce

Easy way to reset single saved variables back to initial state?

GhostAegis 3 years ago updated by Lazlo Bonin (Lead Developer) 3 years ago 10

I'd like to be able to use AoT dictionaries stored in save variables to save large amounts of data in a game (map quadrants that have been discovered, lists of unlocked abilities, etc). The dictionary is critical because it allows easy manipulation of large numbers of entries, particularly when testing in the editor (one click to reset the whole category, since it's all under one saved variable).

However, it seems to me that the only way to reset anything in an actual build is to either: completely reset the Player Pref file, or write a Bolt macro that goes and sets the saved variable to initial state manually (i.e., I have to write a macro that sets every value one-by-one when it's run). 

Neither is really great. Is there a way to reset saved variables from within a build, without deleting all of Player Prefs? Are saved variables saved under individual keys in the Player Prefs that I could then delete individually? 

Also, as an aside, is there any way to force a save or load of saved variables to and from Player Prefs? Looking around I notice that saving is handled when the app quits, and will soon also save on suspend. Does loading from prefs only occur on start?


Edit: I did a quick test, and it looks like even deleting the entire player prefs doesn't do anything. I'm guessing this is because Bolt loads from player prefs on start, then I send the delete all order, then when I quit Bolt saves BACK to the now-empty player prefs with the data it loaded initially? If that's the case, does that mean there's no way to actually reset saved variables in a build (short of manually overwriting them one by one)?

Bolt Version:
Unity Version:
Platform(s):
Scripting Backend:
.NET Version (API Compatibility Level):
Pending Review

Hi GhostAegis!

You're right, there is no easy way of doing that right now, and I'll leave this issue open to research it.

In terms of API, you could do:

SavedVariables.current["name"] = SavedVariables.initial["name"];

If you're familiar with writing custom units, you could create one that basically does this, and takes the name as a parameter.

To answer your more technical questions:

  • Saved variables only get loaded on start.
  • During load, if a variable isn't found in the player prefs, it will get fetched from the initial values.
  • When the app is suspended or exited, the in-memory set of variables will get written to the player prefs.

Good to know, thanks for the quick answer! 

Honestly, that API call is more than suitable for the time being. I haven't made a custom unit before, but with what you've given me here I can make something work without much trouble.

Thank you!

So after a bit of experimenting, I'm noticing an odd issue with that API command you gave me. It appears to work correctly the first time, but then every use after that seems to be overwriting the initial state to match the current state, rather than the other way around.

So I'll load the game (editor or build), hit my reset progress button which calls the API command you gave me, and load up a level. All of my progress is correctly reset. However, if I then make some progress, load back to my menu, and try to reset progress again, nothing appears to happen.

In fact, if I do this in the editor and then exit play, I can look at my saved variables and see that Initial has been changed to match whatever the state of Saved was on the second call of the reset script. It's very odd.

In a build I have to fully close and relaunch it to get the reset function to work (but again, it only works once).

For now I'm just going to have to manually reset everything item by item, but there definitely seems to be a need to manage these more broadly.

Odd, it might be because Application.isPlaying is returning false for some reason. Current is defined as:

current => Application.isPlaying ? merged : initial;

Can you try this instead?

SavedVariables.merged["name"] = SavedVariables.initial["name"];

No luck, using SavedVariables.merged gives the same result. The first use works, the second use causes initial to equal current saved variables.

Any further idea on a potential fix for this? I'll probably switch to a properly serialized save system eventually and just load data into application variables on load at some point, but it'd be really nice to have saved variables for prototyping without having to restart the application for every save data reset.

I can have another look, but I was pretty sure second suggestion would've worked! Darn.

It did not change the problematic behaviour at all?

Sorry about the delay on the response here, but I can confirm it had no effect on the behavior. Totally identical, still broken. I went back and tested again just to be sure.

Not a big deal on my end as I'm only using saved variables for rapid prototyping, but definitely does not seem to be behaving as intended.

Working on Fix

I'll mark this as a bug then and work on a fix.

Cannot Reproduce

Hey GhostAegis,

I tried reproducing the issue but I can't. The API command does what it should, unless I misunderstood you.

using Bolt;
using UnityEngine;
public class Script1934 : MonoBehaviour
{
    void Update () 
    {
        if (Input.GetKeyDown(KeyCode.Tab))
        {
            var newVal = Random.value.ToString();
            Debug.Log("Randomizing: " + SavedVariables.current["test"] + " to " + newVal);
            SavedVariables.current["test"] = newVal;
        }
        if (Input.GetKeyDown(KeyCode.Space))
        {
            Debug.Log("Resetting: " + SavedVariables.current["test"] + " to " + SavedVariables.initial["test"]);
            SavedVariables.current["test"] = SavedVariables.initial["test"];
        }
    }
}

This was my test case in Bolt v.1.4.0f5. I just put that script on an empty game object and tested by hitting Tab and Space.

When hitting tab, the variable changed to a random value.

When hitting space, it reset to its initial value.

If I hit tab again after that, it changed to a random value again.

But hitting space again still reset it back to its initial value, as it should, not the other way around.

Please let me know if you can isolate and reproduce this bug better in a minimal project.

(Along the way, I fixed a small issue where the variables window panel would not update on enter/exit play mode and would only update when the selection changed.)