Transcription
Oh yeah, I made so much progress in this tycoon game that I'm playing that I bought this entire dropper for $0. And it would really suck if I left the game right now and come back to find out that all my progress is now gone. I really don't know whether that is the case or not with this game, if it does have a safe feature. But I guess one way to find out is to log out and then come back into the game a couple hours later to see whether that is the case or not because my mom is banging at my door right now, so I'm going to have to continue this game at a later time. So let's see what happens.
All right, I've finally gotten that taken care of. So let's see if my progress still saves. Uh, okay, well, that sure sucks. Okay, a way we can fix an issue that comes about similar to what we just experienced here is implement a feature that allows us to save data within play sessions for when a player plays the game and then decides to join back into the game and continue where they left off with their progress. We're going to use a feature called a data store that allows us to do exactly what I just said, which is if a player decides to join a game and make progress in a tycoon or whatever game that they're playing and they decide to leave the game and then come back into the game and continue right where they left off with the progress that they did have, um, using a data store, that is how we're going to be able to save the players progress so that they can continue, uh, to do what they want to do.
But data stores seem to be exclusively for player data. But data stores can actually be used for anything related to, uh, storing data within the game apart from player data. That's just one of the most common use cases of using data stores. So in this video, I'm going to show you the basics of using Roblox's Roblox's built-in data store service and how we're going to use that inside of our Roblox games. So with that being said, let me show you further what I'm trying to get out here to understand how this data store works.
All right, let's think about this for a minute. I kind of want to paint a picture of how data stores are structured before we start implementing them inside of Roblox Studio. So let's say we had our game here, which is basically our game that we're currently playing right now, this weird Tycoon that we're playing, uh, and then we have Roblox's servers, which is essentially the back end of where they store all of our information, um, that we would utilize in order to give them information and then retrieve them if we need them, uh, for our game. So then, let's, let's say we had data as like this abstract piece of information that we want to save, uh, from the game's current session that we have here. So if we have data that's lied inside of our game session, so if we're playing the game right now, this is where the data is currently stored. And data could literally be anything. It could be a string, it could be a table, it could be a boolean, just basically all sorts of things that comprise of our players progress, like our kills, deaths, cash, uh, and and our, uh, Tycoon progress, just examples like that. This is essentially what data is. It's an abstract piece of information that contains all of our all of our data. And let's say we took this data and sent it over to Roblox's servers if the player decided to leave the game. And let's say that we decided to join into the game again, we would ask Roblox to give us data that we want to retrieve back into our game. So then we now have the same piece of data that we had when the player left the game to then join back with the data that we now have retrieved from Roblox's servers. And if the player left again, then we would just send it over back to Roblox's servers to keep it safe.
So with this in mind, now let's understand how a data store is structured. So data is very broad because data can be broken up into multiple pieces of data, like our leaderboard data or, uh, or our Tycoon data. So we would basically break this down into multiple data stores, um, that have associated names for them. So in this case, what if we wanted to, let's say, have a data store for coins specifically? This would be the name of our data store. And the way data stores are structured is it's kind of like a dictionary. So, uh, and you know how a dictionary goes, we have a key with a value associated with it. So in this case, let's say we had a key of player one, or it could just be brawl battle like me right here, um, this would be our key right here. And if we had a data store called coins and we have a player, uh, that has a data store inside of our coins that have data inside of our coin's data store, like let's say we had 100 coins inside of our, um, player key for coins. So we have our coins data store name with our player as the key, and then we have 100 as the, the number of coins we have. We want to then, um, put all of this inside of our data and send this over to Roblox's server if we leave the game and then retrieve it back if we decide to join back into the game. And since this is our data store, we can, and that this is a dictionary, we can have multiple keys inside of here. So we can even have player two, uh, inside of our data store, and we can have, uh, let's say 300 coins. So if player one decides to leave the game, we're going to send this data into Roblox's server. And if we join back into the game with player one joining back specifically, we want to take what the value of player one's coins were and give it to the players so that we can start off with 100 coins, just like we did last time, and we can continue our progress and continue this cycle of going back and forth between the game and Roblox's servers to, um, effectively allow us to save data between game gameplay sessions.
So I hope this part made sense to you and gave you a better understanding of data stores inside of, uh, Roblox. So now what we're going to do is start to implement them inside of our Roblox game. So let's go ahead and do that right now. Now that we understand it, let's start implementing data store in our game. But there is something we have to do first before we're able to access data stores inside of Roblox Studio so that we're able to test it while we are implementing these things. Um, and in order to access this and in order to do this, we have to check a setting, but we can't access the settings until we publish our games. So I'm going to show you how to do that in case you've never done it before. So what we're going to do is we're going to go on the top left, hit file, and we're going to hit publish to Roblox as. And it's going to show up this little popup of games that we're going to create. So down here, we're going to hit create new game. And it literally doesn't matter what you call this game. You can just call it data store test, uh, one or something. It, it really does not matter at all what you call it. Uh, so we're going to hit create. And what should happen is now we're going to be, uh, thrown into a published game, uh, to now work with a published game instead of a local file like we have been throughout this entire time we've been creating games. So now that we've done that, we can go up here. So if we go to home and then click on game settings, we have access to all of these different settings, um, to modify our published game. But what, but what we're interested in is we want to go down to security and we want to check this option, enable Studio access to API services. And this basically allows us to access data stores while we're working on our game inside of Studio. And that is very important for us to, uh, and this is very important for us to use. You don't have to do this, but I think it's definitely a lot better to have this as an option. So let's hit save. And now we're able to access data stores while we work on our game.
So sweet, we have that down. So now let's get to adding our data stores. And the place to do this is in a script. So it's probably going to be somewhere like server script service or server storage. I'm going to put this inside of server script service. So we're going to add in a script here. And we are adding a script. So this does not work with a local script. Um, let's delete this code right here. And so what we're going to do is access our data store by saying, local data store service equals game colon get service, open close parentheses, data store service. The first thing we can do, and this really important thing that we have to do, is specify our data, give our data a name so that we know what data we're working with that we're trying to save. So if you remember how data stores are structured based on what I showed you, data stores comprise of a dictionary. Data stores are essentially a dictionary that have a key and a value, and there can be multiple data stores with associated with a name associated with it so that we know what data we're working with so that we can send it to Roblox's servers, save it for us, and give us the option to retrieve it back so that we can use it at a later time. And so now that we understand that, let's try and figure out what kind of data we want to save. So let's say for this example, we want to save a data store of all the players coins inside of, uh, the game that we're trying to create. So what we can do is say, local player coins equals data store service, and the way we retrieve this data store is use a function called get data store, open close parentheses. And there's three arguments here, but the important one that we do need to know about is the name of our data store, which is just going to be player coin. That's what we're going to call our data store.
So now that we have our data store, our data store comprises of a dictionary of keys and values. So you might ask, what kind of key do we want to store within these player coins? Well, I mean, if we're thinking about player coins, ideally all of the entries inside of our data store is going to be each individual player. So how this might look is that if we, let's say, had a dictionary here, uh, well, actually, let me comment this here. If we had a dictionary of player coins, let's say, and we wanted to have brawl battle as our player for the key, and then we're going to have the value of the coin itself, which is going to be like, I don't know, 10 or something like that. This is how a dictionary is structured. You kind of know this at this point. So if we were to translate this into a data store, since player coins is essentially a dictionary, what we would do is if we want to set this data onto our player coins data store, we're going to use a function called set async. And this is what it's going to look like. We're going to give the name of our data store by saying, player coins colon set async, open close parentheses. And we have to put in a key here. So the key in this case is going to be brawl battle. And if this key is not available in our data store, then it's going to add this in automatically, so you don't have to worry about checking it. Comma, and then we're going to add an a value here to our data store, which is going to be 10. So now what's happened is that our empty player coins dictionary now has one entry with brawl battle being the key and 10 being the value.
So now let's say we wanted to retrieve this information. What we would do is wrap this in a variable by saying, local coins equals player coins colon get async, open close parentheses. And all we need to do is set our key. And all we need to do is specify our key, which in this case is going to be brawl battle. And so with that logic, we should be able to retrieve 10 inside of our player coins dictionary. And so we can pretty much just print this value out, uh, when we play the game and hit run. So let's hit run and then see our output to know that our thing is working properly. So as you can see in the output, it has printed 10 successfully after we fetched the value of coins from our brawl battle key inside of our player coins dictionary.
I hope that part made sense to you. So we don't know whether this is actually working correctly or not because we're constantly setting, uh, our key to 10 every single time we play the game. So what if I commented this part out? So now if we play into the, so now if we play the game, all we're doing is fetching the value of my coins. So is this going to print 10, or is this going to print zero? Let's hit run and see what happens, uh, when we join into the game in the output. As you can see, it's still printed 10, even though we did not set 10 to be inside of our, even though we did not set 10 to our player in the player coins, um, data store, because we told Roblox that we wanted to save this information and retrieve it back next time we decided to join into the game. So this is, so this is how you know that the data store that we set is working properly because it saved our previous session and it, and it retrieved our data back into the new game when we join back into the game. So that is basically working as expected.
So that's one method of setting data. But there's another method we can use to increment our data if we have some sort of numerical value, like our coins, for instance, uh, that we want to update. So the way this would work is instead of using set async, all we would need to do is simply replace set async with increment async. So this is what it would look like. We would say, player coins colon increment async, open close parentheses. And so the first argument is just going to be our key, which is just braw battle. And then our second argument is going to be this argument called Delta. And basically what this means is that we're going to take the current value of what's stored inside of the key brawl battle, which in this case it's 10 coins, and we're going to give it an, and we're going to give it another value here to add it onto what is currently inside of our data store. So if we put in five here, then it's going to take our current data store, which is 10, and add five to it, uh, to get a result of 15. And if we wanted to do this the other way around, we would give it a negative value to subtract what our current value is to five rather than 15. But we're going to try and set this to, but we're going to try and increment this to 15. So currently inside of Roblox's data store, our value is 10. So if we join into the game and, uh, let the, let the increment async function run, then in the output, it should say 15, as you can see here, instead of 10, because we incremented, uh, our current value and added five to it. And, and like I mentioned, this only works with numerical values. So this is not going to work with things like booleans and tables and all of those other sorts of things. This only works with numerical data, so like numbers and decimals and those things like that.
So now that we have our data, how do we want to remove this data if we decide that, okay, well, this player does not need this data anymore with player coins, instead of just having it set back to zero or anything like that, we just want to get rid of it completely from the data store. We would use a function called remove async. And this is pretty much what it's going to look like. So if we drop two lines down here, all we need to do is say, player coins colon remove async, open close parentheses. And all we need to do is pass in the key, which is going to be brawl battle in this case. And so pretty much what's going to happen here is that if we try to print this out twice, so if, let's say we wanted to try and, uh, get our player coins, get our player coins data store data store using the key brawl battle, uh, this is not going to work once we remove ourselves from our player coins data store, and it's just going to throw in an error. So let's hit run and see this happened inside of the output. So in the output, as you can see, uh, initially our value is 20 because, uh, our value is now 15 from the last play session and we incremented it again by five, so now the total value is 20. But now that we removed ourselves from the player coins dictionary, uh, when we try to fetch our player coins again using the key brawl battle, it returns null because it no longer exists because we removed ourselves from it. So that is a, a quick and easy way to remove, uh, an entry from a data store if you don't need it anymore. But you could also just set the data back to zero or whatever the default value is as well, cuz remove async specifically gets rid of it entirely from the data store. It doesn't reset it back to its default, um, data store. So that's something I want you to know about if you decide to use remove async in your Roblox games.
Okay, now this next concept I want you to fully pay attention to because I expect you to do this from now on when you're implementing data stores. So, so far up until this point, when we've been accessing data stores, uh, by incrementing them, by getting them, by setting them, and even removing them, we just simply give a blank statement of just incrementing it if we decide to do so, or get it if we decide to do so. But here's the thing about data stores, it's very, it's a very tricky procedure to go and contact Roblox to give us our data that we need and give it back to us so that we can use it in our game, uh, for future use. It's very tricky because there can be a lot of things that can go wrong with trying to do this, like maybe the network was just bad when, uh, we tried to fetch the data, or our Wi-Fi was just terrible, or the game is just extremely, extremely laggy, so it's delayed. There's so many problems that could arise just from trying to retrieve data from Roblox's servers. A very scary example of this would be if a player decided to join into the game and they had so much progress in their game that they're playing, if we just decided to ask Roblox one time, uh, to fetch the data and give it to the player, but then something goes wrong, the player can no longer retrieve, retrieve the data that they need in order to progress through the game. And so because of a little mess up from Roblox's servers or anything that could go wrong with doing this, they now have to start back from square one with zero progress, and you're going to get a lot of hate from players who complain about losing all their data. It's a very scary feeling if you really think about this. If you make so much progress in the game to where all of a sudden one little mis-, one little error happens, then the player will no longer have their data, and it's a very scary and very unfortunate situation to be in.
So now that I've painted that picture for you, how can we prevent this from happening? Well, what we can do is we can tell Roblox that, okay, if the first time we try to get the player data fails, let's try it again, and then we'll try it again, and then we'll try it again and again. What we can do is use a function that Roblox has provided for us called a p call. And this, this is what it's going to look like. So I'm going to comment out all the code that we've had up until this point so that I can demonstrate, um, how we're going to structure our data stores from now on rather than what we just had right here. So what we're going to do is say, p call, open close parentheses, function, open close parentheses, enter. And so now that we have this wrapped in a p call, we're going to let Roblox try this over and over again and tell us what's going on with the code and why it's not working. And this is sort of a way we can, um, fail proof the system, uh, to know whether this worked or not. And if it did not work, then we can do alternatives to try and get our data, um, safely. If, let's say we wanted to retrieve data using, uh, our get async function, p call will return two values. The first value is going to be whether the p call was successful or not, and the second one is going to be our returned value itself. So behind p call, what we're going to do is say, local success comma, uh, current coins, or you can call this whatever you want, it doesn't really matter, equals p call, function, open close parentheses, enter. So from this p call, uh, this will return a boolean of whether this operation was successful or not, and this is also going to return our get async, um, and put it inside of this, uh, variable right here. So what we're going to do is say, return player coins colon get async, open close parentheses, and then our key is brawl battle. This is basically how a p call is structured.
So now we can check to see whether this was successful or not by saying, if success then, and we can basically just print out our players coins, or we could do whatever we want here. Now that we know that it has been successful, we can pretty much say, player coins have been retrieved successfully, fully. And then we can also just return, uh, what the coins are, um, specifically. So now if we go and hit run, we should be able to see that this will successfully go through now that we wrapped it in our p call function, uh, and in the output, it should say, player coins have been successfully retrieved. But because in our previous example, we removed our value here, our key currently does not have a value. It's currently set to nil. So we need to be able to do that ourselves. But this is basically how we use p call to safely know whether, uh, whether this operation was successful or not. And if it wasn't successful, we need to be able to, we need to be able to handle that ourselves. And this is a much safer system than, than just simply using get async by itself. We can even do this with other operations, like setting the data store or removing the data store, and just things like that. We can do that similar to how we did up here with our p call, uh, just by having some slight variations to the code itself.
So let's say we wanted to set the data. Then what we would do is say, local success and then error message in case, uh, we do decide to have an error message, uh, we would simply wrap this in a p call function, open close parentheses, enter, uh, and then what we're going to do is just simply say, player coins colon set async, open close parentheses, put in our key, which is Raw Battle, and then our new value, which is let's say 50 for in this case. And let's then check if, uh, it wasn't successful. Now that we have an error message to let us know what went wrong exactly. So what we can do is say, uh, if not success then, uh, we're going to print out our error message inside of the output, uh, so that we can know exactly what the issue is if, uh, we decide to, uh, try setting data. If we try setting our player data, if it doesn't go out, if it doesn't turn out well, then we're going to know in the output what exactly the error is so that we can fix it ourselves. The reason we're doing an error message instead of a, um, a new variable is because we're not returning anything down here. All we need to do is know whether this was successful or not, and if it wasn't, then we're going to print out the error message. So that's why there's a slight variation with setting versus if we were trying to get something, because in this case, we would probably need the current coins in order to process, uh, what it, whatever it is we want to do with our data. But setting, in this case, we don't care about what the data is because we already know what it is. We just care about whether, uh, this throws an error, and if it does, we need to know what the error is so that we can fix it.
Incrementing will look something like this. So we would have, uh, our success variable and then we would have a return value for incrementing if we want to do that. This is just one example of doing it. Um, we would probably just call this new coins value, equals p call, function, open close parentheses, enter. We're going to say, return player coins colon increment async, open close parentheses, with our key braw battle, and then we're going to increment this from 50 to, uh, let's say 60 by adding 10 here. Uh, that is basically how it's going to work here. We can check whether this was true or not. If success then print new coins, just like a basic example like that. And if we, let's say, want to, uh, remove the data, we would say, local success, coins value equals p call, function, open close parentheses, enter. Return player coins remove async, uh, and then just give the key brawl battle. So in this case, with remove, once we remove our player from the coins data store, if, let's say we wanted to retrieve the value one last time, we would add in our own variable here, um, in case we wanted to use it right after we decide to remove the player data. So we'd say, if this was successful then, let's print, uh, the coin, oh, the, the coins value. And so there we go. These are basically the p call equivalents of these four methods that I've been showing you up until this point.
Okay, so I kind of lied there. Actually, there is a function that we can use to manipulate our data stores that we have in our game. So I mentioned four of them, but there actually is a fifth one, and this is called update async. And by the sound of it, it sounds very similar to set async in the way how I'm going to describe update async. It's basically a function that allows us to change the value of a current data store, but this time given a callback. So I'm going to further explain how this all works, but let's first write it down. So I'm actually going to comment out some stuff here because there's just a lot of code that I don't think we really need right now. Um, so let's comment out all this part after the set async part. Um, so we should have 50 coins by the time, uh, we run the game. So down here, we're going to start writing our update async function. So this is going to be our update one. What we're going to do is say, local success comma, updated coins equals p call, function, open and close parentheses, enter. And so what we're going to going to do now is write, return player coins colon update async, open close parentheses. We're going to pass in our key, which is braw Battle, and then we have this other argument called a transform function. And so basically what we do here is it, it describes it right here. It takes the current value and it returns the new value along with optional user IDs and metadata. But we don't have to worry about that last part. What matters is that we're basically going to take our current data that's inside of this player coins data store and we're going to pass this into a callback function and return the new value and put it inside of updated coins. So we actually need to write our own function for this. So, so before we write our p call, let's write a new function. So we're going to say, local function, and let's say, uh, increment value, just whatever we decide to do with this function. We're going to pass in our current coins, which is going to be in the data store. We're going to hit enter and we're just simply going to return current coins plus, let's say 50. So by the time we return this value, it's going to be set to 100. Let's pass this in like the, the function itself. We're going to pass in increment value as our callback. So now what should happen is we're going to update async, we're going to call the increment value function, and we're going to return 100 coins. Now that we added 50 to our current coins, put it back here, return this here, and then put it in our updated coins. So now down here, we're going to say, if success then print updated coins to, and then we're just going to, uh, concatenate our updated coins value here, just so that we can organize it and understand what this value actually is here.
Okay, sweet. So that is basically how you use update async. So if we join the game, then what we should see is our final result of coins being 100. So it says here that updated coins to 100 because we first, uh, made it so that we seted our coins value to 50, and then we called our update async using this function right here to return 100 after we added 50 to it. And that is basically how update async works instead of set async. But that's still doesn't really answer what the difference is between set, update, between set async and update async. Sync essentially, how I would want you to understand the difference between the two is that when we use set async, we're basically just trying to change a quick value using a p call and not really have to worry anything too much about it. However, there are issues with using set async that update async might do better, and that is, uh, being able to try multiple times to be able to set the value that we want, uh, our value set to. Because what happens with set async is that if we have set async and we try to make this work, it's probably going to set it correctly. But let's say we had two set async happen at the exact same time. Oh, sorry, I'm still in testing mode. What if we had two set async happen at the same time? There's probably going to be some inconsistencies here on whether which one is going to, uh, set first. Um, it's probably going to be 100, it might be 50, we don't even know because, because this one might do it faster than this one. So there's an inconsistency when it comes to that. But it's definitely a quicker solution to the problem that we're trying to fix. It's faster as well, and it's less complicated to do. But if we wanted to use update async for situations where we want to be consistent with the data that we're trying to set this data store to, would be using like multiple attempts to try and make that happen while also making it safer, we would probably use update async. But the issue with this is that it might be slower than if you try to use, uh, set async for like one value rather than trying to set multiple values instead of just one. That's kind of a superficial explanation as to how the stuff works, but I hope that sort of gives you a general idea of which ones you should use over the other one when you're trying to decide on whether you're using set async or update async. But generally, you could use either or, you could use only one of them over the other if you really want to, or you can use a mix of both of them. It really does not matter that much unless you're being very specific with how you want to handle your data stores. So, so that's pretty much that.
Okay, now there is one more important concept to learn about, and that is with the use of scopes. So in order for me to let you understand how this stuff works, uh, let's paint a picture of of how we would organize our data stores. So let's say we did join into the game and we want to save multiple pieces of data, um, we would probably do something like this. We would have one for player coins, we would have one for, uh, I don't know, player gems, we would have one for, uh, player kills, we would have one for player wipeouts, and you, you get the idea. Like if I kept going down this list, it's going to get very, very, very, very disorganized, very, very fast. So, and so I think that says a lot about how we organize our data stores if we were to try to do this strategy to do this sort of stuff. So that's why I want to introduce you to the concept of scopes, and this is essentially a, and this is essentially data stores within data stores so that we can organize our data stores, um, when we're working with multiple pieces of data that we're trying to save in our Roblox games. So the way this would probably work, uh, let me just try to demonstrate this with an example. Um, let's say we had player inventory, but our player inventory could be comprised of many, many different things. Our player inventory could probably be, uh, coins. How this would work is it would kind of work like it's a direct directory or folder by using a forward slash and say, uh, coins. So our coins is a data store in and of itself inside of the player inventory data store because we have multiple data stores inside of the same data store. So this is probably what it would look like down here with gems. In this case, we wouldn't have to say player coins and then player, uh, gems and things like that, because how we were accessing our data, uh, from this up until this point was basically have our data store and then have our key, which was brawl battle, uh, and then we'd basically do the same thing here. But there's definitely a better, but there's definitely a much better way of doing this by using scopes to specify specifically what kind of data inside of our main data that we're trying to access. So, um, if we're doing coins, then what we're accessing for a key is going to be brawl battle, and then the same thing is going to be said here. So I think you kind of get the idea of what I'm trying to show you here with scoping. This is essentially how we specify and organize our data stores when we're trying to work with multiple pieces of data that we're trying to save. And so that's what I'm going to show you how to do, uh, right now. So if we wanted to specify a scope of, let's say, player coins, uh, what we can do is we can first specify our player inventory to make it more broad. So we're going to say here, local player inventory equals data store service colon get data store, open close parentheses, player inventory. And now let's say we wanted to get the player coins, coins being a directory of player inventory, uh, as the scope. What we're going to do is say down here, player coins equals data store service get data store. This time it's going to be player inventory, and we're going to pass in a second argument, which is going to be our scope. This is going to be our coins right here as our scope. We're going to say coins, simple as that. So now we have access to our coins part of the player inventory. And this leaves for more organization when it comes to our data stores that we're trying to use in our game. And so everything here pretty much works exactly the same way. It's just now we have an extra layer of organization with our data stores. So that's a little quick tip that I wanted to give you for that.
So finally, we've OD all the important concepts of data stores. Now let's actually put them to practical use, uh, inside of our game. And what we're going to do is create a leaderboard for the players when they join into the game, and we're going to actually save the players coins and, uh, retrieve them whenever they join back into the game. So this looks a little messy right now. So I'm actually going to create a new script on the right side. So on the right side, let's disable our current script and let's add in a new one over here. So we're going to call this player added. And then we're going to first access our data store service, which we can just copy from here and then paste it into here. Uh, and then what we're going to do is access our player inventory with our player coins. So we could just copy these as well and just put them over here. And now what we're going to do is add in a player added event. So we're going to say, game.players.player added colon connect function, open to close parentheses, player enter. And now we're going to create our leader stats folder. So we're going to say, leader stats equals instance.new folder. And then we're going to put this inside of our player. So the parent is going to be set equal to player. And then we're going to add in our coins leader, our coins leader stat. So we're going to say, local coins equals instance.new int value. And then we're going to set the parent of the coins to the leader stats. And so now we have our leader stat. But what we want to do now is we first want to fetch the player coins that exist within Roblox servers if it does exist. So, so what we're going to do is say, local success, current coins equals p call, open close parentheses, function, open close parentheses, enter. Return player coins colon get async, open close parentheses. Now, up until this point, we've been using an explicit key, which is our name brawl battle. But now you might ask, we've made a player added event and we've added leader stats to our player. So if we were to, let's say, have a player coins data store that we want to give the information to Roblox and send it back to us, uh, that's distinguishable from each player, what's the key going to be? Ask yourself this question right now. What would our key be for our specific player if we were to designate a specific value to our player's key? What would the player key be? Would it be the name? I don't think it would be the name because if we had the player's name, like brawl battle, I could just simply change my name with with a 100 Rob, with a thousand robo to, I don't know, braw Dev, and all of a sudden now when the, when that player joins back into the game, it's not going to be the same data associated with that player. So what bit of information from the player can we use that will stick around for the entirety of that player's time on Roblox? Their user ID, right? Their user ID is going to be the only thing that will stay within the player whenever they leave the game and then join back throughout their entire existence on Roblox. Well, unless they get banned, of course. But they, they didn't deserve to play her game if they got banned in the first place anyway. So that's not on us. But with this in mind, our key is going to be our player.userid. And that is the key we're going to use for all of our data stores if we're deciding to save our player data. This is going to be the key right here. Okay, and we're going to check if this was successful. So we're going to say, if success then, what we're going to do is set our coins int value. So coins.val, we're going to set this equal to the current coins that exist inside of the data store already. We're going to set that equal to current coins. And if it does not exist, we're going to throw in an else and we're going to say, coins.value equals zero because this is going to be our default value. And if it doesn't exist, and if it does exist, then we're going to set the coins value to what it currently does exist right now.
So what we can do to know whether this is working is by using increment async so that we can increment our value every single time we join to the game. So what we're going to do is say, local success, updated value equals p call, function, open close parentheses, enter. What we're going to do is return player coins colon increment async. We're going to pass in our key, which is going to be the player.user ID, and then we're going to increment this by 10 every single time. Let's just say that as an example. So if this was successful, then what we're going to do is is update our coins.value to our new value that had that the data store has been incremented to. So we're going to say, coins.value equals updated value. And so this is basically our entire script right here that we need to know that we need to do in order to test whether our leader stats is actually working properly or not. So this is pretty much it. Let's go into the game, let's hit test, and let's hit play to see what happens when we join into the game. Okay, there's one thing I forgot to do, and that was to change the names of our leader stats and our coins. My bad on that. Leader stats.name equals lowercase leader stats. And then coins will be equal to, uh, coins.name equals coins. Simple as that. Okay, so now let's go into the game and see our results now that we have this all sorted out properly.
Okay, so now that we're in the game, um, well, I, I joined into the game a couple of times, so this doesn't really count. But basically, what ended up happening was that when I joined into the game, it tried to fetch the information of coins that we had in Roblox servers and add 10 to it since we joined into the game. So it's currently at 30. Let's stop the game and let's try joining into the game once again, um, to see our change. So it's going to check if we have our, um, 30 coins first, and then it's going to add 10. So first it was 30, and then it quickly added another 10 to it to now have it be 40. And we can pretty much just do the same thing again if we leave the game and then join back into the game. And you basically get the idea of how leader, of how we can apply data stores to saving player data. So this basically works every single time, and we have now successfully saved our player data using all the information that we've learned about from this video, uh, and apply it to our Roblox games. So this was a long video, but this is one, but I can't emphasize how important data stores are to Roblox games and how confusing it is if it's your first time using Roblox data stores. So I hope this video gave you a really good insight into how data stores worked, and it's okay if you still don't quite understand it well just yet. It really just comes down to practice, and the more you do it, the better you will get at it so that you can successfully save player data within gameplay sessions.
Before I end this video, I want to say a couple of things about data stores that I think, uh, it's that I think are good tips to know about when you're implementing them is that data stores do have limitations. You do somewhat have to be careful when when overusing data stores because Roblox's servers can take in a specific amount of data before throttling it because there's just too much data overflowing within their servers. So one tactic I would use for data store service is to instead of update the data store every single time that their coins change, I would incrementally just save the data, uh, through certain sessions. So what I'm talking about here is that I would probably have like a while true do statement here, and then I would probably say like, after waiting every 60 seconds, we would try to successfully, uh, save all the data that's currently within the player, or, or things like that. So we don't have to try and set the data, uh, every single time we update a value, uh, within the player. We could just incrementally do save sessions periodically, uh, to save the amount of time that we save our data within Roblox's servers so that we're not overflowing their systems when we do that. That's like a, that's like a tip I can give for that. Another tip is to use scopes in your data stores, of course, because it's very disorganized if you try to do get data store for every single bit of data that you're trying to save. And so that's another thing I want you to try and get into practice of, uh, when you're using data stores and you're trying to save a lot of data. What I would also try to do is try and use a table that can basically translate to the player's inventory. So instead of having like a whole, so instead of having like a whole data store as a scope for the player inventory, what you could do instead is have a scope for, let's say, uh, shop statistics or inventory statistics, like I don't know, specific sections of the player inventory that doesn't need to have a whole data store for. Instead, what you could do is just have one table full of all this information to then have it be stored inside of one data store instead of all of these different data stores, uh, using scopes, cuz scopes allow you to organize your data stores, but if you don't need to use scopes, then you don't have to at all. My general advice to this would be to use tables when you're trying to, uh, store multiple pieces of data that all sort of relate to each other that don't need to have different data stores for each single thing. And so that's pretty much everything about data stores. I hope you found this video to be extremely, extremely valuable. This, I'm pretty sure, is the longest episode inside of my Advanced scripting tutorial series. So if you can do whatever you can to support what I do with my channel and things like that, because these videos are really fun to make, but oh man, these videos are getting harder and harder to make by the day. So what's important to me is that you're watching my videos and you're taking in every bit of detail that I try to explain to the best of my ability, uh, with these videos that I tried to put out for the channel. And I can't thank you enough for sticking around on this journey with, like, this episode that we're on, like episode 18 or 19, and things like that. I kind of just want to like say this a little bit before I go because I'm very proud of how far you've come with this series and, and, and this channel in general. Like I'm sending a message to you specifically, the person who is watching my videos, who is watching these very long videos of me explaining these things and putting them into practical use to become a better Roblox developer. So that's just something I wanted to say now that we're, we're at the end of the video. This is probably one of my favorite videos that I've uploaded to this channel, so I wanted to make it special. So that's going to be it for data stores. If you want to learn another somewhat confusing topic like C frames, I made a video on that not too long ago. So I encourage you to watch that video that I'm going to have for you right here if you haven't already. But with that being said, I will see you in the next episode. Take care.