How to Build A Save System in Unity

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments

Cool topic, but I always have wondered why people make these code videos when making a text one with images/gifs is way more practical, easier to navigate, and indexable.

👍︎︎ 9 👤︎︎ u/Slight0 📅︎︎ May 30 2019 🗫︎ replies
Captions
unless you're making a retro game and trying to infuriate players by throwing them back into the error before hard drives or memory cards you're probably going to want to let your players save their progress in your game if you're working in unity you've probably searched for ways to write a safe system and found numerous results showing you to use the built-in player prefs feature you've then probably realized that this is fine for small games or projects that don't need to store a lot of data but if like me you're building a fairly complex game with lots of data you want to store you're going to want a more functional solution than writing hundreds upon hundreds of entries into the player pressure system so let's do it a different way hi there i'm matt and welcome to game dev guide today we're going to use binary formatting to build an extremely flexible safe game system the plan here is to build a custom safe game class that holds all of the data we want to store then when we want to save our game we'll write our safe game class to a text file and when we want to load the game we go the other way casting back from the text file to our custom class so there's three main components here firstly there's our game classes that need data stored secondly there's our save game class that will hold the data and finally a serialization system to actually handle the saving and loading of the text file with that in mind let's get started the first thing we'll do is create our serialization script let's create a new folder called serialization and a new c-sharp class could serialization manager the first thing we'll do is write our save method this will take in a save name string and the object we want to save will also return a boolean to confirm that the save was successful in a separate method we'll define our binary formatter this method will create will eventually allow us to define serialization surrogates for our formatter to use more on that a bit later for now though we'll just return our binary formatter back in our save method we'll define the path for our save game you could define anywhere on the system but I'm a fan of using the persistent data path and creating a safe folder in there with the save name and a custom extension which will just call dot save for now then we'll create a far stream at our path and use our binary formatter to serialize the object then close the file stream and that's the saving handled we'll write another static method called load which will take in a path to load from well then check that the path exists get our binary formatter again and open a file stream add our path will attempt to open the file and if it works will return the saved object and just in case we've accidentally passed the wrong path into our loading system we'll make sure our whole code base doesn't implode by catching it with an error and returning a null object instead with that finished let's move on to the star of our show our save data class let's create a new C sharp class and call it safe data we'll make it a singleton and create a new reference to it if one doesn't already exist the key to our safe system working is that classes we want saved are marked as serializable we do this by adding the serializable attribute to the class header anything within our save file should be serializable by the binary formatter so any additional classes we create that wish to have their data stored will also need to be marked as serializable to demonstrate this and to test if our safe system works let's create a new class could play a profile this will hold some information about the player such as their profile name how much money they currently have and their experience level in our saved data class we'll create a public player profile called profile and we'll also add some resources let's suppose the player can buy toy cars and toy dolls with their currency and we want to keep track of how many of each toy they have to test this out I've built some UI where the player can either click a button to start a new game or load a previous save if they start a new game they're asked to input their name and this is saved to the profile data as well as some default variables they're then taken to a second screen which shows their name and has a button to buy toys or work if they click the work button they gained some currency and experience if they buy toys they spend some of the currency and gain a toy as you can see we're tracking this data in the UI when any of these buttons are pressed we're updating the data in our save system if I choose to save make some more changes and then hit the load button to go back to that save the load button simply replaces the save data class and tells our UI to update restoring the state from our save and the same thing happens if we restart the game and choose to load so that's great it looks like our save system works but we're not done yet right so as you can see I've taken the toy box analogy further our prototype has developed a bit now and we've got toys we can spawn and move around I want our save system to remember which exact toy to save and where it is in our play space so things are a bit more complicated the binary formatter doesn't support unity classes such as game objects transforms or vector 3s out of the box which means that we can't just create a list of game objects and expect our system to save them instead I've created a custom class for our toys and and a list of them to our save data this class is marked as serializable and it has an enum for the toy type a string ID a vector3 for its position and a quaternion for its rotation we give it an ID so that any other object that relies on it can get a reference to it upon loading again you're probably also wondering why I'm storing position and rotation when I literally just told you that both of these things aren't serializable by the system well that's because we're going to need the serialization surrogates I mentioned earlier a serialization surrogate is essentially used to tell our binary formatter how to serialize classes that aren't natively serializable so for the case of vector threes and quaternions we need to create a serialization surrogate we do this using the AI serialization surrogate interface and then tell our interface how to handle the data for each type we then add this to our list of surrogates until our binary formatter to use them it's worth noting you could probably extend this further and create surrogates for all of the properties of a mana behavior to make it completely serializable but I try to limit the data I handle as much as possible anyway with our setup let's tell our toys to add themselves to our save data when they're spawned if they don't already exist we'll also make the game object destroy itself when the load event is called in case it needs to be replaced and to update their data when they're interacted with then when we load we'll tell our game to go through the data set and spawn each toy based on its enum placing it in a safe position and rotation if we try it out you can see our system successfully saves and loads are more complex toy data thanks to our sterilization surrogates the only problem with our current system is that it's pretty old-school as it only handles a single save file at a time we ideally want to support multiple save files fortunately that's actually a pretty straightforward modification to make to our system let's create a save manager class this class will act as a buffer between saving and loading our game in our save manager will tell it to get a list of all of the files at a specific directory and store them in an array [Music] then all we need to do is build a UI for it like so when the player saves they're asked to define a save name which our save manager users to save the game when they choose to load the save manager displays the list of files from the directory in the UI and when the player chooses the night um in the list we call the load method passing in the index of the item they've selected and there you have it easy multi file saving with just a few more simple steps as you can see this is an extremely useful and flexible way to handle saving in your game you're mostly just redesigning the way that you handle data management in your codebase rather than writing numerous lines of code for each individual data point you want to save so hopefully there's something useful in there for you let me know if you've learned anything new and how you might use a system like this in your game below also be sure to subscribe for more game dev tips tricks and tutorials and if you're interested why not check out some of these other videos across the channel as always thank you very much for watching and I'll see you again next time
Info
Channel: Game Dev Guide
Views: 103,271
Rating: undefined out of 5
Keywords: unity, learn, games, gamedev, how to, making games in unity, tutorial, unity tutorial, learning unity, unity3d tutorial, programming, making games, saving, loading, save system, player prefs, serialization, binary formatter, c# save, save manager, load manager
Id: 5roZtuqZyuw
Channel Id: undefined
Length: 9min 40sec (580 seconds)
Published: Mon May 27 2019
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.