How To Save Your Game In Unity® with JSON | Serialization Tutorial - XML Alternative

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey guys and welcome to another unity tutorial and in this one I'm going to cover saving your game in JSON this time in not xml simply for the reason that I think JSON is a lot more modern and it's starting to become this norm so unity has this really simple method for storing JSON using the JSON utility class it's basically to JSON or from JSON and that's about all you need to do so I'm going to start by explaining what is going to be going on in this tutorial and so I first want to cover how our components and non component classes are going to work together so in this example we're going to be using components to communicate with sort of how the game works so where do I put you know game objects where do you game objects go and classes are going to act as more of data which they are data structures and they're going to be storing all the information that the outer program that isn't exactly the game needs to know so that it can in turn store all that data in JSON and then the game can then contact it and say hey I need to load all this JSON up against that I can you know in our case put the characters where their save locations work okay so to cover what sort of components that we're going to have and what classes we're going to have we'll start with saying we're going to have this actor component which is going to communicate with the game and share the actor data with it so it's going to have an actor data attribute and our actor data class is going to have a structure of you know health position and maybe some other details and so this actor data is going to be shared with our saving and loading system and it's going to sort of act like I made a middleman between the game and program like we were talking about earlier with components versus classes so we can get started right there and I'm going to start by creating an actor component so c-sharp script is a new thing to create and I'll type an actor here okay now I'm going to open this up but I'm not going to start with actually creating anything in the actor class itself what I'm going to start with is working on our actor data class since it's more of an abstraction and doesn't really have any dependencies on other classes so the actor data class is going to be this class is just going to store three things we're going to have a string which is a name we're going to have a vector three representing the position and we're going to have a float representing health of the character okay and now we want to add this tag up to the top here called serializable and now this won't pop up in intellisense immediately you'll need to actually right click on it or hit ctrl period and write using system if you're not using an IE then you can just include system by writing using system up there and it'll figure it out so we put the serializable tags that unity is able to store this in json ultimately so I guess I'll show you what that means in a second so right now I'm going to start filling in whatever data we need in the actor class and one of those examples is that we need an actor data attribute new actor data and we're just going to make it a new actor data office start as we'll store things in it as the game happens so when we save our actor data is going to be filled in RAM and then we eventually write it to a file okay so we'll make an example string of a name here we'll call this guy actor and that'll save his name oops I'll put string name equals actor okay and we want a quick exam full of health we won't we'll be manually editing that okay and so now I'll add in whatever functions that we can use right now we don't really need any of those model behavior functions okay so our first one is going to be storing data so this is going to be what happens when we store data inside of our actor data attribute so do a public void store data and we're going to first store a name and you can probably guess what comes next considering we want to store everything that is relevant so data doc position equals transform that position and data dot health equals health okay now we want one that's very similar which is going to load the data which pretty much does the opposite so here's some grunt work for you name equals dude name we basically just want to reverse these oops so this would be closed dot actually data dot pose sorry about that is going to become our new position and we want our health to be our data's health and if this doesn't really makes sense now or it seems kind of redundant sorry I only rename this let me just say this is going to store inside of here and then whenever we load it's going to pull whatever is from there so the idea is once we overwrite these saves load data we'll figure it out later which is the concept of saving and loading in general so we're going to put in a an on enable function and an on disable function but we're not going to fill anything in these point yet as we have another class which is going to have these events and once these events fire the actor will know hey I need to save or hey I need a load so we'll get back to the actor class in a bit but very quickly I want to make another new script and this one's going to be an actor container and this is another representation of JSON think of this as a representation of our actors attributes in JSON so we're going to go and make another script in unity and this one is going to be called actor container actor container and we can go ahead and open this one up okay now this is another example of one that's not going to be a mono behavior similar to our actor data class and that's because it's again a JSON representation so let's pull out these smart load functions and we're going to create another serializable serializable class so I will use system again and also going to need to use system not collections dot generic because we're going to be using a list and this is going to be a list of actors so a list accurate data sorry I didn't want to have a discrepancy there but it's going to be a list of actor data that's going to be representing our actors in the file so we can just quickly initialize it and that's all that we need to do here because we can just now access that whenever we want to make a new actor data so that's you're actually an actor container sorry so when we load using this JSON utility it'll figure out what we're supposed to be doing when that happens so what we're supposed to be doing is making a new actor container so we can grab all these actors from it so now that that's done I'm going to go ahead and make our save data class which is going to be probably our most code intensive and that's because it's kind of all the logic that's going on when we save and load so I'm going to go back into unity and create another new script and this one is going to be called save data as I just mentioned so save data okay all right so again this is not a lot of behavior and it does not need oddity of your functions all right so first I'm going to specify an actor container because this is going to represent the actor container of the entire game so every actor is supposed to be stored in this actor container when we load the game so we will again initialize it just so that we can use it whenever we want to and the reason why this is static is so that we can just have one actor container and just access it from our save data class so that we don't need to make a new save data class every time we want an actor container because we want this to be easily accessible there are other ways to get around this but for this example I'm just going to be using a static variable okay so I'm going to want to specify a delegate type here and if you don't know anything about delegates don't freak out it's not a big deal all you need to know is that we're going to be using this as a type for our events we're going to have an onload event and and on before save event so let's write these out right now so public static event serialized action which is the type of event unloaded and we want to have another event with the same type on before save so this happens after loading unloaded and on before save happens right before saving of course and the idea behind these events is that they're going to be storing a lot of our actors data and we can actually hop over to our actor class right now because this is where we're going to be using these events just like we don't jump back to it later so the first thing we want to do is write save data dot unloaded plus equals load data so this means once this event is fired this is one of the actions that's going to happen once this is fired so we call unloaded somewhere in the save data later on but for now we will just fill it up with things okay so save data dot on before save is going to also add on stored data and one more thing which is apply data and we want to obviously do apply data right after store data because we're going to store the data and then apply it to the actor so oh and speaking of which actually we're going to write this function later so I'll just leave it commented out really quickly and the other thing I want to do is we need to undeceive all remove these from the events because you typically want to have somewhere where you in an event add stuff into it as in you know functions or whatever and then you want to remove them at some point in your program and undone enable and undisciplined you can put them just because they happen you know when the game object enters the game it'll do this once the game object leaves the game it'll remove them and you don't want to leave them hanging I won't go far into why you don't want to leave them in there because it's a bit beyond the scope of the video but just understand that you want to have these removed at some point okay so let's go back to actually I need to write this quick function of idea by data and this will eventually and the actors data to a list in the save data but for now we don't have that function so let's go back over to our save data and get back to what we were actually doing so why don't we first write our load function so alright public static employed load and this will take a path of where we want to load so so first I will edit the actor container here and this is going to use load actors okay now the concept behind load actors is that it is actually part that's going to load everything from JSON and so we might I'll write these functions quickly actually so here let's write our static load actors functions so private static actor container load actors and this again takes string path because I need to know where that JSON file is so first we want to say string JSON equals file dot read all text from that path we've I need to include some sort yeah so we want to use system dot IO up here make sure you write that in and I'm going to just return JSON utility JSON sorry JSON utility dot from JSON and we want to give it the type of actor containers that it knows what it's trying to parse the JSON into and we want to pass it our string of JSON so basically what's happening here is we're loading all the text out of a file into a string and we're going to assume that the string is JSON and then we want to then parse that JSON into an actor container type and then we're going to return its let this function can then store it here so if we uncomment this then it is our actor containers not going to be filled with whatever was in that JSON holder and a file sorry and now actually just with only that code our loading functionality does work and that's why I like the JSON utility class because it makes this sort of thing much easier ok so now I'm going to write our save actors function so write private static void save actors again we want a path where to save it and we want a container of actors that we want to shove in this JSON file so first we're going to make another string and this is going to be using JSON utility again but this time we're going to be changing a container of actors to JSON actors so this is obviously going to be this actor container up here which is going to be filled with a bunch of actors by the time we save it here excuse me um okay so I'll write a stream writer really quick w equals file dot create text in the path and basically this function is going to if the file doesn't exist it will make the file and fill it with everything if the file does exist it will override it and just put whatever was in this string there so now I want to do s talita close sorry I was actually uh I was actually incorrect the purpose of this is it's going to create that file and if it's if it already exists then it will override it however it's not going to fill it with our JSON because this is just the part that will create the file now what we want to do is write all the text with right alt text at that path and using our JSON string okay so these two functions are done and we have a couple of other helper function that we want to add in so our first one is that at actor data function that we saw before which is a little redundant it's going to add the actor data to the actor container so actor container dot actors that add data okay and let's do this similar thing with clear actor data well actually it is very clear actor list it doesn't need to take anything because all it's going to do is access this actors attribute and we're just going to clear it basically okay and the purpose of this is that we don't have duplicate data because whenever we want to save in here we need to clear is the idea so before we save we want to clear so let's see and not before we save sorry after we save F and after we load we want to clear so let me go ahead and write in a couple of actually I'm going to write the save function this should be the last one we have public static void save and it's going to take a string path and actor container of actors of course and the first thing we're going to do is call our on before save event so every time this function is called we throw off everything that was stored in on before save we also want to do save actors and we're going to use path and the actors in this argument list primary list sorry and then we want to clear of course so clear a cue list so again we want to do everything that's on before save which is going to be in our actor class and we want to store all of our actors as JSON inside of the file then we're going to clear this actor container just so that we don't have any duplicate data set next time we save we don't have any sort of nests in there okay now that that's through we can move on we actually have more stuff to write in our load function but we're going to go to our game controller really quick and put in some code in there something can finish up this load function actually right before we do that I believe I can just uncomment all these so that we ensure that we actually add the actor data once we write before we save so that's what's going to be filling up the actor container so I'll go back here and again to unity where we're going to create a game controller class okay so game controller okay and this is going to be a model behavior this is going to be a big one in basically telling unity what it's even supposed to be doing it's a good example of how a components is considered the communicator with unity okay so we got a couple of things in here these will be used later save button button and we have another button oops which is going to be used to load and we're going at the right using unity UI in the engine that you watch okay and these are just going to be the buttons that will trigger either saving or loading okay so let's see we want to have a player prefab so that we can create it player prefab okay and we also want to have a path of where we want the data to be stored so that's going to be our persistent data path but we need to initialize it with just a empty string so alright string.empty and now we're going to write a quick awake function avoid awake okay and in our wake function we want to set our data path to be system dot IO dot path combined and that functions it basically is just a path combiner it will combine strings that we put inside of it with a backslash basically so application a persistent data path which is a unity attribute basically it's it's a data path you can use across all your platforms so it makes it really easy to store data somewhere and it's a good place for save data especially okay so then we have actors dot JSON and this is going to be the name of the file that all the actors are going to be saved into and yeah so we can move on from there I don't believe we need an update function will we might use start we will not use it now that's for sure so I want to first have a create actor function so actor create actor okay so the idea here is that we want to create we want to spawn in a prefab that's using our actor component so turning in rotation and this is supposed to be position okay and we want to have a hopefully actually a paprika have already so game object game object equals instantiate oops instantiate prefab at the position with the rotation well just as a game object okay and so actor actor equals game object that get component actor now if we don't have an actor component we want to add an actor component okay and if you're new to this operator this is your favorite I'm sorry if you notice this operator that just means if this first one is null then return the second one so that means if it has no actor components that we're going to go in here and create an actor component and then return it and so that's what this add function is going to do it's going to return one that it adds newly so then we just want to return that actor okay now oh okay yeah we should all right I will add in a game object and object prefab okay and then what's free kept in here okay because that's a static function all right so so first we want to have a save function void save actually is to be a public save function and here we'll write save data dot save data path and also we want to be using the actor container that save data is storing all the actors in okay now we want to use another function called load owed okay and this is going to be doing save data dot load data path okay so now we can just easily drag these two functions to our buttons and run these save functions okay so we're in unity and we can actually add a game controller component to an empty game controller object and I have these two UI buttons here so let me pick these so under save we want to save button stored and load we wants a load button oh and I actually just realized we don't really need those to be stored in the game controller what we can do instead is go to save button just click on our UI elements and it should have a button component and on this button component we can just add a functionality to on click and we'll pick our game controller object into our game controller model behavior and click on save and we'll go ahead and do the same for load so almost so pick the game controller with a function of load okay now we have a player here with a player controller that will that's pre-made that should be included so we'll add on a an actor script here and we'll call this guy Joseph or something and he'll have like 50 health oh okay I see and so if I just run this so we have our player here and say we want to move around so I move them over here and see the positions and I will hit save okay so now save should store this in a file with only one player inside of a JSON structure but before we go and look at that I want to point out that in our project settings this is where we determine what the name names of the folders that that JSON will be stored in is so on Windows you're going to be going into your username so C Drive users username and then your app data local low and then this company name here and the name of the product which is the game name and so we have our actors JSON file so theoretically this actors that JSON file should now only have Joseph in it and there we go see we have an actor container which is represented by these parentheses here there sorry brackets and actors is a key which points to a JSON array which contains only one object okay so now we can see that he's in a position 14 on x 1.5 + y + 5 his health is the same as we said and of course his name as well so now let's go back into unity and see what happens when we actually load this okay now before we load I want to point out that our load function is oh actually I believe our loop function may be incomplete so let's go to load save data load okay so sorry about this we want to go ahead and finish our load function really quickly and then we can see how this works okay so we want to do a for each years for each actor data data in actor container that actors so we're going to cycle through every actor that we have stored in our actor container we want to do game controller dot create actor using ours data and our game controller dot player path which is going to be basically where our player prefab is stored they could also yeah why don't we just go ahead and make a player path which is going to be um player path in my unity project it's in prefabs / player well actually it's in resources so let me show you really quickly it'll be in resources prefabs and then player so so in save data we're going to use that player path and as well as that player path we want to use data position and the quaternion dot identity so because we didn't actually serialize any sort of rotation it's just going to be that okay so great oh yeah so in our game controller you have a straight path and game object prefab oh okay I see let's write another helper function in our game controller it's going to be another create actor but this time it will use data so actor create actor and the idea behind this one is that it will actually use our actor data so we use actor data data will have a string into our path position and a rotation okay and we go okay so our actor is going to equal our other create actor function using a path our position and our rotation and now we just want to store that data in our actor and return that actor okay on takes the oh yeah so we want our prefab we use as a player for a phobia so player freaked out okay alright so now oh oh I say okay I made a little stake here oh okay yeah sore mistake was just we don't need to actually use this prefab we will just do game object prefab equals resources dot load game object at that path and then we'll just load the prefab from a string rather than using our function over here okay so now that that create actor function is done which is basically going to create an actor using this function and then store its data go back in save data oops they do excuse me and go ahead and finish this one up okay so save data after we do create all these actors we can pretty much just call on loaded that way every actor knows what to do after the game is loaded and then again we want to clear that actor list so that it's not so doesn't have any duplicate data in it okay so let's go back into unity and oh okay and what I'll do is deactivate this player and once I hit the load button and load the player that we originally saved I mostly like this guy should be named Joseph is 50 health and it looks like his position is the same and that's perfect so now what we can do is clone will have some fun and make a couple more of Joseph post and Bob and we'll call this guy Ron okay and oh I'm writing in the data it's how I want to do okay so this guy will be wrong you'll have four health and this guy will be Bob and he will have ten health okay so now I'm going to hit this Save button I'll take these guys over a bit actually looks like I am physics problem here okay whatever that'll that'll make it easier okay so hit save here and let's actually check out our JSON file so yeah looks like we have Ron and one of these guys went way up on the y-axis here's what we have an 88 okay so I'll minimize this and I'll hit play and once I load they should be back where they were and it looks like they were and here's Bob in space okay so that's going to be it for this one I'd say big takeaways were just obviously serialization the concept of components versus classes and we had some delegate and event work in there so if this didn't really make that much sense maybe if you go through it again it will otherwise I'd say why not try going with some simpler examples or maybe something more I guess focused on those specific concepts we're having trouble with events maybe go and check out some events tutorials or do some practice with them but that is going to be all for this one make sure to leave a like if this helped you and hit the subscribe if you want to see you know all these videos that I make and if you want more unity tips and other sorts of game development stuff and make sure to actually also check out the websites Infinity dotnet I've been posting a lot more there as well but in the meantime I will see you next time [Music]
Info
Channel: Omnirift
Views: 23,241
Rating: undefined out of 5
Keywords: JSON, unity C# tutorial, unity tutorial c#, save games in unity, how to save games in unity, json serialization in unity, unity json, unity json serialization, JSONObject, JSONObject Unity, JSONObject.ToJSON, json serialization unity, save games unity, unity serialization tutorial, unity save character, unity save level, unity how to save games in xml, unity how to serialize in xml, unity how to serialize in json, unity xml serialization tutorial, save game in unity json
Id: zPhtjcNTMN8
Channel Id: undefined
Length: 37min 16sec (2236 seconds)
Published: Wed Dec 28 2016
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.