Saving & Loading Games in Godot (with demo)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
today i'll be talking about saving and loading games in godot i'll also be going over a demo that implements saving and loading at the end of the video so stay tuned till the end to see that whenever you think of saving and loading a game you probably only think about saving and loading a game on disk but there's more to it than this much more let me explain you see whenever your game runs godot loads a scene into memory and graphs it onto the scene tree and whenever your game chooses to load a different scene the same thing happens only this time the old scene is freed up in the process but what happens to the state of things from that old scene that information is lost unless we capture it somehow and then reapply it whenever that scene is reloaded being able to do this will enable us to develop much bigger games with more scenes okay so let's back up right before the scenes are changed now in the godot engine you switch scenes with a bit of code like this and so it's right before we call the change sync function that we want to capture game state from scene 1. so how can we do this well since we need the game state to survive each scene in our game we need to add what's called a singleton as that name suggests this is an object in our game where there's just one of them but they are also called autoloads because they are automatically loaded when a game starts and is present until the game exits so we need a singleton to store the game state data we'll call it a gamestate service or gs service for short we also need something to capture gamestate for game components and reapply that state later to do this we'll add a child node to each component that needs game state persisted we'll call this a game state helper node so each time the scene is switched the game state service will first call the helper nodes in the old scene to capture game state and then call helper nodes in the new scene to reapply its game state so right about now you're probably wondering how the helper nodes know what needs to be captured this is done with an array of property names let's take the player scene for example here we want to persist the player's position in the game world as well as the direction they are facing so we just add these property names to the save properties array as shown but not all game state can be boiled down to just a property on a node sometimes you have to write some specialized code and for that the helper nodes have two signals called loading data and saving data when you connect a function to these signals you get a dictionary object with which you can store or retrieve anything you want so far we have a singleton working with a helper node to persist and restore a component state each time scene is changed let's go over some other scenarios we have to handle if we want everything to work smoothly one scenario is having an event in one scene affect the game state in another for example we have a trigger in one scene when the trigger state changes we want a door and another scene to be opened in order to do this we need the trigger's game state to be made available to the door in the other scene what hasn't been mentioned yet is that each scene's game stake data is kept separate from the data of other scenes this keeps things tidy but also prevents game state from being messed up due to key collisions so what we need is a global area for game state then all scenes can share game state data we can do this easily enough by adding a flag to the helper node called global this will cause the game state service to give the helper node a reference to a global dictionary that any component can look at so in this example both the trigger and the door will have their helper nodes marked for global then they might need a bit of code to handle some logic on top of that but at least they can now share that data another scenario is around dynamically instanced or spawned components at runtime let's say you have a scene where enemies are being spawned when the scene is reloaded what we want is for these enemies to be respawned automatically and their game state reapplied to do this we introduce another flag to the helper node called dynamic instance when this flag is set the helper node saves off the scene path for the enemy as part of the game state data the presence of this path data causes the game state service to instance the enemy again and at back to the scene it then calls the helper node to reapply the game state data the last scenario is kind of the opposite of the spawned enemy scenario here we have an instance child scene one that is added to a parent scene at design time in the ghetto engine editor for example let's say it's a mini boss in a game level the mini boss is added at design time in the godot engine editor but once the miniboss is defeated we want it to be gone for good to handle this we have the helper node detect when it's leaving the scene tree at this point it emits a signal that the game state service is monitoring the game state service makes a note about the freed scene in the game state data then when the scene is reloaded the helper node seeing the note about being previously freed frees its parent node again okay so now we have a lot of scenarios covered we capture and reapply game state on each scene change we enabled game state to be shared globally allowing for events in one scene to affect another we handle respawning things like enemies and maintaining their state it will even handle the freeing of child instant scenes to keep them from appearing in the game from then on so that just leaves the actual saving and loading to a file there are a few ways to do this but the one i favor is using a resource file first we'll need a new script that extends the resource class in it we add an exported data property and a game data version property then all we have to do is use the resource saver class to save an instance of our new resource and to load it we just use the resource loader class the nice thing about using the resource saver and loader classes is that they automatically handle the serialization and parsing of good old types if you choose to use a json file instead you'll have to handle the parsing of these types manually the downside of a resource file is that users can open them up and make changes even if you choose to use the binary format with the json file approach you can encrypt the file with a password to keep that from happening however i think the most likely issue is that people will modify a game file accidentally or that it might simply become corrupted so rather than encrypt the file an md5 hash can be used to check if the file contents have been altered since it was saved now that we've covered how to save and load a game file let's get into the demo the demo is available on github feel free to download it and use it any way you'd like link is in the description the demo is a top-down dungeon game each dungeon room is its own scene and each room demonstrates one of the scenarios we've just covered we have the main room with a locked door to open the door you have to do certain things in the other rooms the hud has a view game state button which displays the game state data as you can see it's a dictionary with nested dictionaries inside it the metadata section lists the current scene path so we can reload that scene when loading a saved game from file then we have a global state dictionary which right now just has an inventory items array in it since we have nothing in the inventory it's empty next is the scene data dictionary each scene's data is kept in a separate dictionary which is keyed by its scene file path we already have data here from the main room each room exit has a locked flag for its game state with the north doors lock flag being set to true the player also has some state data for it its global position and facing direction note that each component's data is keyed with a note path this means that moving nodes around in a scene may cause issues with previously saved games so if you use the game state service from the demo just know that once a game is released and players are saving games it's best not to move things around if you have to for some reason then some sort of path translation will have to be done to older save files the scene to the left of the main room demonstrates the scenario of maintaining spawn components add more of them with the green button and subtract them with the red button the spinners are respawned each time you enter the room interacting with the floor switch will affect the state of a pedestal in the main room also note that now in the game state data we have a west trigger entry in the global state dictionary with a value of true this is how scenes share state so that events in one scene can affect another the scene to the right of the main room demonstrates a scenario of a freed instance child scene the barrier or wall in the middle is freed by activating a floor switch and it stays freed from then on in the game state data we can see the entry for the low wall that has been freed here we see a flag set to true this flag is what tells the game state helper to re-free its parent node as with the other room the far floor switch affects the state of a pedestal in the main room the scene to the south of the main room demonstrates picking up an item and putting it into an inventory we can see the item id for the key in the inventory item array now so the inventory will be maintained from scene to scene once the switches are activated and the key collected you can then open the door in the main room lastly you can save a game in the pause menu and load previous saved games a mini screenshot is saved as well to give context to the saved game so that's the overview of the demo let me know if you have any questions or comments about it or the scenarios we covered earlier i hope you found this video useful if so give it a like and be sure to subscribe so you don't miss my next video on game development
Info
Channel: Jason Lothamer
Views: 900
Rating: undefined out of 5
Keywords: Godot, Godot Engine, Save and Load, Game State, Persistence
Id: _gBpk5nKyXU
Channel Id: undefined
Length: 11min 29sec (689 seconds)
Published: Fri Nov 12 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.