Most optimal way to set up multiple save slots? (SOLVED)

image

You’re telling it to use a number variable (GlobalVariable() pulls number/value variables only) instead of a string variable, which your GameSave.CurrentSlot is. You need to use the appropriate expression for GlobalVariableString.

Thanks, the error is now gone.
Unfortunately, now nothing works. Saving doesn’t save the data to slots a, b, or c anymore, but instead it just makes an entirely new child in the structure:

Did I forget to add something?

You seem to be saving just a “slot”. You should be saving the entire save structure every time.

Otherwise you’re only going to have the slot in your saved data, and therefore overwrite just down to the top level.

Edit: I’d make sure to clear your storage entirely and see what gets saved after an attempt. Maybe your expression isn’t set up right, or maybe it’s not getting saved.

Okay, I’ll run a test:


Filled in some values (Before saving). Currently selected slot: a


After saving. Slot a didn’t change, but an entirely new field of parameters appeared in the Saves structure instead of saving to a specific slot. It even grabbed the “CurrentSlot” value and put that in there. If I change to a different slot, it simply changes the “CurrentSlot” value in saves.


After shutting down the preview and booting it back up again. The values from before are still saved in those parameters, but not loading in properly. Loading and deleting does absolutely nothing to any of the code or stored values.

Here’s all the code again, with all the updates:

I have a feeling that simply storing it in Saves isn’t going to work as intended. Do I need to add an expression to specify which slot to save it to?

Edit: Here’s the global variable structure too if it helps:

--------------------UPDATE--------------------
I’ve changed the code to look like this now:

As a result, saving now works! It now properly saves to the selected slot!

However, as you can see in the screenshot above, the CurrentSlot value is added as a child of the structure, which ideally I don’t want. Will I need to move it outside of the GameState variable?

Also, loading is still kind of finicky…
Here I have all 3 slots filled up with something. When I restart the scene, everything stays loaded in their slots:

But once I close the preview and relaunch it:

Only slot a has it’s values stored. Slot b and c were wiped.
In fact, slot a literally stole the values from slot c???

Deleting still doesn’t work properly, but it’s likely because I still have some of it’s code disabled for now. We’ll cross that bridge when we get there.

I’ll keep tinkering, but do you have any pointers?

That looks like the save slot child structure isn’t being read for saving and/or created upon loading. You might need to reevaluate your dynamic expression, and you might need to wrap the whole thing within the brackets inside of a ToString expression.

How would I do that? I’m not sure where I need to put ToString, and there’s no autocompletion to work with either. Everything I try to type returns with an error.

There’s a few things going odd here.

  1. I still think you should not be saving GameState at all. you should be applying the GameState to your save slot then save the entire save structure.
  2. You changed from brackets to parenthesis, which won’t work. It’d be something like Saves[ToString(“Saves” + CurrentSaveSlot)]
  3. You should probably remove the “current slot” from your GameState and have it as a separate global variable, especially as it doesn’t need to be saved.

Alright, I’ve switched to brackets and added ToString, but I still get an error thrown back at me:

I’m confused on not saving GameState though. Do you mean I don’t even need the GameState variable at all, and I should just be saving directly to one of the three slots depending on which slot is chosen?

If so, then going back to this code for example…


Does this imply that I need to replace every single instance of GameState with “Saves[“Save”+CurrentSaveSlot]?”
For example: Saves[“Save”+CurrentSaveSlot].EXP, Saves[“Save”+CurrentSaveSlot].Money, etc etc?

No, Gamestate is for your currently running game. Not saving

You apply the gamestate to your saveslot child variable right before you save, then save the saveslot structure variable in full. Gamestate itself should never be saved to storage. This is important incase the player realizes they screwed up a choice/death/etc and wants to reload the game without daving. If you are directly using the save slot for game logic it becomes much harder to go back without messing with storage even more.

The inverse is true when loading. At the start of the game you should load the entire saveslot structure, then when selecting a game slot you load that slot child variable over gamestate in full and then start the the game.

Super high level.
Save: Gamestate > Slot A > SaveSlots to Storage

Load;Storage to temp variable > temp variable to Saveslots > Select SlotA > Gamestate

I don’t have time to check proper dynamic variable syntax, but if you fix the above it will help you overall. I’ll try to check specifics sometime this week.

Ahh yes, I see, I have to take what’s in GameState and save it inside of Saves.
The thing I’m struggling with is HOW to do that…
According to this post, it can be done with JSON. In that case…
Do I need to use JSON to move the values to another variable, and THEN save them in Saves?


What I’m trying to do in the above code:

  1. Use JSON to move the values from GameState to Saves.Save(CurrentSaveSlot) in this case, a.
  2. Save the entire Saves structure.
  3. Immediately load the entire Saves structure, and parse the loaded JSON so that the text updates dynamically.

When I tried it this way, it didn’t work. The debugger shows that it’s just creating a new structure in the Saves structure instead of saving it in the selected slot. The error says that it’s unable to parse the values too.
I can’t use the ToString you suggested because it still gives me an error when it’s typed.

I’m aware WHAT I have to to, but I have no idea HOW to do it, or what events I have to use to accomplish it. Is using JSON to move the structure correct?

So I did a quick test:

  1. You should separate out the “CurrentSlot” variable into it’s own separate global variable, this is tripping you up and bloating your structure. It should not be saved at any point of the game and is only used when the player selects a save slot
  2. The new variable format structure makes it a bit easier, so it’d just be Saves[“Save”+CurrentSaveSlot], or if you’re not declaring variables, it’d be Saves[“Save” + GlobalVariableString(CurrentSaveSlot)], but you shouldn’t need this
  3. You will use the “GlobalVariabletoJSON” expression AND the “Convert Json String to global variable” in a few different places.

Here’s a quick mockup, I tested it successfully. Note that I am using “VariableString” in a few places as a test/old habits, so long as you are pre-defining your variables you can just use their name directly.

I did read some of your conversation but well too much for my dyslexia to go trough

I did read what Silver suggest to you
But i wonder why not simply use different Storage for save slots?

You have saving and loading as simple as it gets

Which you most likely are able to do

NOW
In my post i save to Storage named Storage

Assuming you have 3 buttons (You could have as many as you want 3 is just for example) there where they have different colors

Now imagine for Red button i am saving to storage named Slot1
Now i copy paste that event and for when Blue button is clicked i save to storage named Slot2
And so go on

And now you only care about about what button is pressed and to what storage name you are saving (I think you could even go with different group names like Group1 and Group2 and so go on instead of storage with different name)

I would say it is a lot easier than managing actual slots via strings

Separate storage will totally work fine, but requires more events.

The original ask was for most optimal way to do multiple slots, so the dynamic variables used in the events example I gave leads to the least amount of events needed, and if they decide to add more slots down the road, no new save/load events would be needed

Instead of storage name as Storage1 Storage2 and so go on
Where one for each slot would require separate event
It could be storage name → Stoarge(GlobalVariable(SlotID))

And now there would be only need of manipulating one variable instead of duplicating events

Wouldn’t that be better?

That would also totally work fine, but leads to the same number of events as my method above, and doesn’t really reduce complexity.

You always want to have your current game state structure be a different variable than your saves (to allow for reloading without having to go back to storage) and you want to avoid writing to or reading from storage frequently (to reduce situations where it is still being written to or loaded from when the player closes the game or a crash happens, because that can lead to corruption of the storage data or entire storage db).

With using a dynamic storage name you are still having to mix expressions and events, so there’s not any reduction of complexity. If it’s easier for shadow or you to follow, it’s totally fine. Just ensure you are keeping the above in mind.

1 Like

Oh my, it turns out I was greatly overcomplicating things, your solution works out fantastically, and I understand what I was doing wrong as well!
The CurrentSaveSlot was already moved outside prior, but I also tweaked the code, make the storage names more clear, and changed the slots to uppercase letters for convenience.

That being said though, I still have a few minor issues remaining:

  1. Manually loading to a slot isn’t applying the values to the GameState. When I press L to load, the GameState doesn’t inherit the values, nor does the debugger change values.

  2. Deleting save files doesn’t seem to work as intended. Ideally, I want to press X to wipe all the data in the current slot clean, poof, gone, reduced to atoms.
    Unfortunately, when I restart the scene, all the data I just deleted is loaded right back in.
    Even more strangely, the debugger clearly shows that the values have been reset, only to load them back in once the scene restarts??? What else to I need to delete the data permanently?

I can’t speak to your specific scenario, but as far as I know overwriting global variable A with another global variable B does not delete variables that exist in A but not in B, it just updates matching variables or create new ones that are missing. So you may be deleting your saves, but your GameState still has its existing variables.

I’d either make sure you have a “Defaults” global structure that you can overwrite GameState with at the beginning of the game (Opening scene or menu or whatever you prefer, incase you reset to menu after deleting a save), or add an action to delete the children of GameState as well.

Having a defaults structure for a new game is probably useful/important, though, incase your player ever loads a game, dies, then decides to just start from scratch.

1 Like

Thank you for the insight, I thought about it a little more, tinkered with it, and discovered that if the game is saved after deleting, the file STAYS deleted. Therefore, I made the game automatically save after the deletion of a file:

And yes, I’m aware that making default values are important for new games and such, but I appreciate you bringing it up for some foresight.

We’re in the home stretch now, there’s only one last issue that I just couldn’t wrap my head around. When I press L to manually load the game (As seen in the screenshot), the GameState values don’t change, not ingame, or in the debugger, so manual loading isn’t doing anything.

Basically, what I want is that when the game loads, the values from whatever slot I have selected would be applied to GameState, which doesn’t happen.

I’m using Saves[“Save”+CurrentSaveSlot] to try and load them in. Is this incorrect?

You have to use the GlobalVarToJSON() expression around it in order for it to work in the “Convert JSON String” action to work.

1 Like

Awesome, it’s up and fully running now! I’m surprised by how simple it all really is too!

I want to thank you kindly for being so patient with me, your information was immensely helpful. I’m very grateful you stuck this through with me until the end.

1 Like