@@Ambitious_Aligator not every british person sounds like AlvinBlox, but him specifically sounds a lot like him, they probably live quite close, who knows.
I'm so glad I stumbled upon your channel, this is actually pretty informative and your way of explaining is clear and direct to the point. Keep it up, spread the word and my man, you are going places.
Thank you Thank you Thank you!! This is my first exposure to class creation and multi-file script management in Roblox, I learned so much from this one video
Can you show how this would be implemented if you wanted to do a 3 Slot Save system, where for each slot you can either Create a New Game or Load Game.
Oh my lord, you are so clever! I learned plenty of things from this, I especially like the graphics you put up to make the subjects much easier to digest
@@AshRBX_dev I wanted to ask you if I could make a video in which I explained how to make a system to use that data somehow, for example by taking the value of 'coins' and creating an IntValue inside a folder within the Player, Thanks in advance even if you can not make a video.
@@gigione104 I probably wont make a video expanding on this system. However, if you have discord join the AshRBX discord server which is linked in the description of all my recent videos. DM me on there and i will create a document that will show you how to do this for you with a RBXL file example.
why do we use semicolon ain this lua?, BUT TYSM NOW İ DONT A HAVE A PHOBİA OF DATASTORE edit: NVM WHY DOES İT NOT WORK WHEN İ PUT PLAYER.NAME BUT İT ALSO NOT WORK WHEN İ DONT PUT İT HELP GUYS WHYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY
Great video! But I think that at the part of building the constructor function, it would be better to name the second parameter not with self, cause it could confuse people about the second self there. Also, you forgot to mention that it could be necessary to use Session Locking to prevent some scenarios ( and update async is better for this )
Thanks so much for this! Just a question though how can I connect to the PlayerClass from another script to set and update values and have those also save and load. For example I have a money spawner and when I walk over it the touched event should give me money but that script is in a completely different area
I think you could call the same function like he did in the "on join Table" when the player already has existing data. So u just need to require the contents from the PlayerClass through the Id of the player and get the result and then you should be able to use the function from the PlayerClass like"addCoins" or something(I have no idea if that actually helps bec i have not tried it but from my understanding of the vid it could work??)
It depends on your coding style imo, Data stores V2 is still an amazing tool and is used by so many people. I shared this one just based on how I would program outside of Roblox and is useful for me because I have external experience with other languages. So for me, I prefer this one 👍👍
Really really good tutorial i just subscribed! Was looking for something like this 2 years ago and here it is! Did you learn all this by yourself or university/school?
very in-depth tut and good video - fyi anyone watching this in 2024, make sure you download the script in the description there are a few lines of code that have been added that weren't in the video, not sure what they're for but it makes it work lol though i am trying to see if this can be used to save checkpoints in an obby type game so when the player returns they show up on the same checkpoint, if anyone else is trying to do the same let me know if you figure it out before me lol
This is usually a common issue that can be fixed by going to the game settings in the home tab, going to security, and enabling studio access to API services. Let me know if this helps 👍
Great video. But I think there might be a better way of doing this. If the format of the byte changes, instead of manually converting the data would it not be better to create a new database? For example, v1 of the game you use database "profile_v1". If you remove something from the player data, you create a "profile_v1.2". If the player is using an older version, then you simply get the data from the old database and add it to the new. This will allow you to rollback, and reduces the complexity of the code. Thoughts?
Just like everyone else I absolutely love this video even though I don’t understand some parts it is still an amazing and extremely informative video but I just have one question of why do you put semicolons at the end of almost every line of code?
I really like this OOP way of handling player data. How would one implement this in a game with stats when you cant see the data and structures when testing? Would you write a loop to create player folder data or just do logging until you ironed out the code so no players see the data on the client side?
this tutorial is pretty good, but the json encode is pretty redundant as when the Roblox saves things inside its datastore it already encodes the data using json, therefore, adding another layer of json encoding will only make the data longer and add more things to store
its probs habit from other programming languages like c# or java, it doesnt do anything in lua as in you can have it if you want or not at all (it doesnt matter)
Apologies for the slow response. This is just a practice I’ve used coming from other languages, the syntax of lua allows for the use of ; so I use it it’s completely optional 👍
Hey, great tutorial but I have a question! How would I modify the player's values from a local script? For example, if a player clicks their screen their coins would go up (Like in clicking simulators).
To get the class data in the client, you can set up a remote event system such as the one I go over in my server client communication video. To get this data you will have to call an event or function that returns the player Class to the client. However, I prefer it over other methods.
Hi! I don't know if youre still looking through notifcations or comment sections. However, if you are I would love to know how or if you could store a player item using this system. Whether it is a weapon or something of the sort, i'd love to see it done! Youre doing amazing thank you very much for these videos.
i tried that too but there is a better method. I personally just save the name of the item as a string value and when the player joins you can just check the saved names and assign the tools you have saved somewhere in your game to the players backback by cloning them.
Thanks a lot for the video, it really helped me out with my game! If I may, can I ask you how to update the attributes of the player class (say "coins" and "level") with new attributes I added after the first login of my character? Because when I load my place all i see printed are the old attributes existing on the previous save, but the new ones are not indexed in the table I get, so my character doesn't have them initialized. I think new characters would have them all set on their first login, counting a total of 5 attributes instead of the 2 my current character has. Thanks a lot in advance and sorry for the silly question
Very useful info (you've got a sub from me), but why is the audio so weird ? Like it's been stitched together from multiple recordings. Makes the whole thing a bit annoying and hard to follow. Uncanny valley or something, like when you're not sure your dialogue partner is entirely human or not. Why don't you make a scripted dialogue for the entire thing, once the video is in place and read it in one go ? Would me it so much more easy to follow along.
Nice tutorial! But how access the data now from another script, like displaying the coins, or add levels? should make the server script a module script?
i was reading other comments, will be good to make an external module script, with a function like "AddPlayerClass(playerId, playerClass)" and every time the onJoinTable add a playerClass to the playerClasses, added it to with the AddPlayerClass to another table in the module script, like a copy? would be the player class still synchronized and keep updating?
check this code people, for adding more content to store in future game updates, change the first part of the playerClass script with this and add a copy of the ForLoops as child: local playerClass = {}; playerClass.__index = playerClass; function playerClass.new(player, oldSelf) repeat task.wait() until player.Character ~= nil --if oldSelf then return setmetatable(oldSelf,playerClass) end local self = {} self.name = player.Name self.character = player.Character self.coins = 0 self.progress = 0 if oldSelf then local function overrideKey(key,value) if oldSelf[key] then self[key] = oldSelf[key] end end require(script.ForLoops).pairsForLoop(overrideKey,self) end setmetatable(self,playerClass) return self end
Yes from using this many times after I created it it is more efficient to make the playerclasses table into a module script and access but you can also make the whole server script a module script and access the data from there 👍👍
Hey, I had trouble implementing profileservice into my game, so I was wondering if according to the title, this method is actually better or equally as good as profileservice?
The difference between profile service and this Class method is that profile service specialises in saving and loading data from data stores. This method however specialises in not only saving the player data but organising it so that you can use it more efficiently within your games for example you can obviously attach functions to the class and use inheritance and polymorphism within your classes which you cannot do with profile service. In the long run, Id use this method but profile service is another good tool if you are only saving and loading data with it.
@@AshRBX_dev okay thank you, the reason I don't use profileservice even though its a good tool was because it can't replicate the profile data to the clients, and sending remotes constantly for lets say a player clicking, would result in throttles.
@@AshRBX_devprofile service has much more features built in. Everything you said abt organizing player data is still possible with profile service. (Just a module handler for getting or setting data). It's good that u used OOP in your code, but It wouldn't help solve the main problem of 90% of data stores. I mean data loss, dupe, etc.
@@rostats6451and some additional info: profile service is about data. It's not about replicating it somewhere else. But u can use tons of network libraries or make your own to replicate data between client and server
Btw I had a question remember when the roblox data loss in october 2020? is it hard to script recovery data? like if a player loses their data how to developers have backups and restore their data?
I have a few questions on the datastore. Why does the onJoin table have result == nil or result == "null"? I never encountered 'null' before in lua, and the way you wrote it looks like a string so could you explain the difference between nil and "null"? Also, you get userid's from the players name, but wouldn't just doing player.UserId be more effective in case the player changes their username later on?
Yes, I’ve had a couple suggestions about player.UserId, this should be the way you do it, for some reason my brain didn’t think of it at the time I made the program 🤣. To answer your question on the null item, “null” is just a string that I used here to make sure that it hasn’t been saved as a string named “null”, this is for saving purposes. As an extension I will usually have it save “null” if the data needs to be reset or something similar. It’s mainly for debugging because you can just set it to nil here, so if you aren’t going use null anywhere, you can delete the or statement and keep it as onJoinTable[result == nil]
@@AshRBX_dev Okay, thank you for clearing that up, and also, you're the only channel I know that replies to videos made long times ago, so keep up the good work!
A bit of an issue I am having, I am trying to introduce a new value, however it will only ever work for first time joining players as the script returns the loaded table after checking if it exists. Any fix?
One way to do this is instead of storing all of the instances in the table inside the Server script, store the table in a separate module script and require the module script when you need a player class
To clear the players data, all you need to do is set their table in the playerclasses table to a default player class, so just set the playerClasses[USERID] = playerClass.new(parameters) this will make a new default player class and when the player leaves this default one will save
This is probably one of the quickest ways to set up data storing, and if you like doing it this way then definitely do so. However I prefer this method because your programs will be more organised, you can apply aspects such as polymorphism, inheritance and encapsulation which you cannot do with leaderstats. Furthermore, you can attach different functions into your classes which allow for again more organised programs in large games.
so i have a remote event to send a button click to the server script, and ive been putting all the code to change the datastore in the OnJoinTable false area, but every time a client clicks the image button it sets everybodys playerdata to be the same, how would i get the client to only modify their data?
Another great video that I am having a problem parsing data. But on another video that I don't know where I got. i remember putting in a version of the dataStore so that way you can update the stuff you save and then it will be version 0.0.2. Plus was a way to test brand new dataStore because I am not quite figuring out how to dump my current save that i think happened when I closed the game because it is saying player data was found. I will copy your scripts and see where I missed in the videos. But great stuff. On this topic say you made it to checkpoint4 in the game and on the player coming back to the game. The teleport section you have in PlayerClass would you have and conditional that if not new player be like self.Character.HumanoidRootPart.CFrame = loadedCFrame so that it teleports to that point of the saved game? of course would have to have saved that info but am I thinking in the right spot for that?
Yes you can either add a conditional to the playerClass or use the server script in the video with the onJoinTable and put it in the place where we have created a playerClass for an existing user. You could then move them to the point stored in the datastore maybe it was stored in the playerclass as a checkpoint variable that equals a string with the checkpoint name.
@@AshRBX_dev Im stuck. Cannot seem to get passed an error Cannot Parse Json. and I think the problem is a save that happened because I cannot get it to clear that and start a new player. And I am trying to figure out where I can put the version like above but it's not working to make it think its a new player. Where do I dump the file that got saved so that I can run the script again as a brand new never been player so it creates the save all over.
@@Jscodin To be totally honest. I have not dug back into this since I had posted this. I think I propbably beat my head into the wall too much and wasn't getting any reply I had moved on. But I can see where I was trying to go. I wanted to place checkpoints if player makes it to this point then unlocks a different set of variables to happen from that point forward. And if they wanted to go back to a place to complete something not completed they could but could not move forward. But then I believe i got stuck on terrains because i wanted to transport to a different terrain all together for the checkpoint. Then life tended to get in the way as it does.
How do you save data from a player who added ability like for exemple muscle mass on a gym simulator so when they get back in the game it retrieve the data from the progress the player made instead of getting the same 50 value again and again ? I followed your tutorial and applied the logic for my gym simulator but I can't seem to wrap my head about how to make sure it save the data each time I modify the value so for exemple I start at muscle mass 50 and when I bench I go to 51 but the problem is I get back in my game and everything is lost so the player has to restart and it's annoying
I'm pretty much a beginner in coding but I think I understand how your code works and it works in my game. I was wondering @AshRBX how you would actually use the saved data to create things such as a store where a gui button detects how much coins a player has, and takes away coins so a player can buy an item or something like that? I'm just stuck on the part of getting the loaded data into a script to create that what if statement so could you help me with that? I've seen multiple of your videos and they're very helpful for learning and work great!
Hello, I want to ask you a question. When I try to change the coins value with another script, I get an error attempt to index nil with 'value'. What should I do? Also thanks for the video
If you are trying to access the player class from another script, you need to reference the object that is in the player classes table. How are you trying to access the coins of the player from another script? Are you using events?
local PlayerClass = require(script.Parent.Server.PlayerClass) PlayerClass.coins.value += 100 I'm trying this but now I realized that I didn't write which player's coins value will change, how can I do that?
@@deathanqel2077 This definition of the playerClass is slightly incorrect. when you want to create a new player class for a player, you need to use the .new() function in order to create it. The example here showing how you create a new player class: local playerClass = require(script.PlayerClass).new(player); The player parameter here is just the player that you are creating the class for. Then you can do: playerClass.coins += 100 Hope this helps. If you need any more assistance let me know
sorry to bother but won't this code create a new player? I want to change the coins value of a registered player.Thank you for your time and patience with me.
Ah okay my bad for misunderstanding, if you have already created a new player class, it should be getting stored in your Playerclasses table that will be in the server. If this is the case, you can access a player class from the playerclasses table in the server class by using the player ID like it has been set up in the video. So if you’re in the server script, you can write: playerClass = playerClasses[USERID] where USERID is the players ID. This will get the playerClass linked to the player. Remember, when accessing a value from the player class self table, you need to just reference the variable you want to edit. So don’t use playerclass.coins.value += 100. You only need playerclass.coins += 100.
Nice video, but when we get the userId, I just did “player.UserId” This is because we are getting the userId from the Username of the player, but what if the player changes their username? That is a feature that roblox allows, so what if this happens?
how do i use this code where do i save the value to i cant read the coins values or level values how do i use this edit: i shouldent have gone to the advanced tutorial
The best practice for this is to save the playerClasses table as its own module script. This will then allow you to access the player info from anywhere on the server. To access data on the client, you will need to use remote events to request data from the client and return it back to them from the server
Hello, this is a fantastic video! I am have an error with one line though. Line 39, in the playerJoined function, it keeps attempted to index nil with “name”. I suspect maybe it’s trying to get the name before the player has fully loaded, but I am unsure how to fix this. Any tips? Thanks again
@@magpietaxi I have learned basic programming, and have run into this problem before with other codes I’ve done. I was just wondering if you had a solution I haven’t been able to find yet.
How would you implement a custom table of players to start with the new player class data whether or not they already have saved data? In instance, you would have a table of exploiters users IDs and want to restart their progress?
You could have another table of user IDs underneath the playerClasses table that are hackers, and when the player joins you can check if the user’s ID is in the hacker table. If it is, then only call the function from the onJoinTable that sets all of the players data to the default (as if they’ve joined for the first time)
A couple of ways that the issue can be fixed: - Check your data store API is enabled, go to “game settings” in the HOME tab, then click on Security, then make sure Enable Studio Access to API Services is enabled. This will enable data storing. - if that doesn’t work, in the description there are paste bins to the main scripts used in the video, you can copy and paste the link into Google to find the code to each script and use that code to test if it works. - finally, if this doesn’t work, I will be creating a discord server soon where you can send me screenshots of the broken code and I will try to help debug for you 👍 Sorry for any inconvenience from the video, let me know if you have any more issues
@@shadowwolfex The best way for this system is to move the player classes table into a module script that is accessible to other server scripts. To achieve this, you can create a new module script that returns an empty table (keep the module script the same once created). Then in the server script replace the assignment of the playerclasses table to require the new module script you made (rather than creating a new table in the script). Then you will be able to access the data classes from other scripts. If you need further help be sure to join my discord
Yo. I'm trying to connect a coin value from this script to the leaderstats. However, I see that in my output that my leaderstatsscript loads before the playerdata loads. Therefore when the leaderstatsscript runs, the script just assumes the playerclass is nil, therefore indexing my .coin with nil. I've tried to use a simple wait() function at the start of my leaderstatsscript, however this doesn't work, and will also not be a good idea... My function in the leaderstatsscript is ofcourse a PlayerAdded:Connect function. Do you have any idea how I can fix this problem :)
So you can save it without converting to JSON, but this can cause risk of data corruption inside the data store itself and I would recommend storing it as JSON, JSON converts the table into a string format and datastores only allow for you to store strings, numbers, booleans. This means that using JSON is highly effective and that’s why I used it in the tutorial. Hope this helps 👍👍
You could use this to save the name of the item they have then give the item to them when they load in, this method will only save strings, bools, integers so using strings to store names of items would be a good use for it
local display = script.Parent.TextLabel local player = game.Players.LocalPlayer local leaderstats = player:WaitForChild("leaderstats") display.Text = leaderstats.coins.Value
To get the player classes to another server script, you can either use remote events from the player script -> script you want. Or, you can move the playerclasses table into a module script and access that module script using the require() method from the other server script 👍be on the look out for a new datastore video that is in the works, it is more advanced than this one but will be worth it and will cover this problem
Hey Ash, i am curious about one thing. How its gonna save the new parameters of the module "PlayerClass"? So, for example, the player joined, script created its own new table with given attributes to save. Then he leaves. The new update releases, and it got new currency named "gems". Developer puts it in the constructor. The script sees that player already got result table and sets it as it was. New attributes will save for new players after the update, but not for players who played before. Is this works like that or i may be wrong?
I see your issue, and that is a valid point. What I would do is where we check the playerClass for an existing self table when we create the player class, instead of setting self to that previously saved self table, just loop through the self table inside the constructor that will set the values of the new self table to the values in the old one. This will then mean that any new variables you add after an update are carried over as well as your old values from the saved one. You can add checks to see if you've removed any variables too. So say the variable Coins was saved, and you removed coins in the update, you would check to see if coins exists in the new self table, and if so you can then go and replace the new coins value with the saved one. Hope this helps.
check this code, for adding more content to store in future game updates, change the first part of the playerClass script with this and add a copy of the ForLoops as child: local playerClass = {}; playerClass.__index = playerClass; function playerClass.new(player, oldSelf) repeat task.wait() until player.Character ~= nil --if oldSelf then return setmetatable(oldSelf,playerClass) end local self = {} self.name = player.Name self.character = player.Character self.coins = 0 self.progress = 0 if oldSelf then local function overrideKey(key,value) if oldSelf[key] then self[key] = oldSelf[key] end end require(script.ForLoops).pairsForLoop(overrideKey,self) end setmetatable(self,playerClass) return self end
You can do this by firing a remote event from the server script and listen for the event call in your local script, you can send the data from the player class as an argument to the event and get it in the local script to then place onto your ui 👍
Yes this is true, as an extension of this if the server is open for more than 24 hours after the players leave you could remove the player from the PlayerClasses table as if your server stays open forever and you keep getting players you will get a memory leak. However keeping them all for a period of time after allows for data to be saved just to make sure the last player that leaves the server has their data saved as well
@@AshRBX_dev yea i removed the playerClass in the table after the player leave and his data has been saved, futhermore i added that every 5 minute it save data just to be more secure
You would use a remote function from the client to request the players data. So on the client side you would call the remote function which could be called “getPlayerClass” and then in the server script you can listen for the event and return the class that belongs to the player using their player ID. This then gives you access to the coins value that’s in your playerClass and you can display this value on the players UI
To add new stats, go into the playerClass module script, find the constructor and in that .new() function you will see the self.coins, stuff like this. To add EXP, just add self.exp = 0! This will be your default EXP value for when a user newly joins the game.
@@ErolsaurusIf you need, i have a discord server linked in my most recent videos, DM me from there and I can help in further detail on things that are not working as they should :)
here is the line I get my error: local playerClass = require(script.PlayerClass).new(plr, http:JSONDecode(result)); -- sets attributes to our new class, I can an errror saying: Can't parse JSON, I really liked this tutorial so I won't give up if there's any way to fix this please tell me because I finally found a data tore tutorial helpful and now I understand dataStores so I'll keep rewatching until I fully understand
One way to possibly fix this error is to make sure you have the data store API enabled, go into the settings in the Home tab, go to Security and enable the Roblox studio API option 👍 if this doesn’t work, join my discord server which is linked in more recent videos and message me there and I will take a closer look for you
@@AshRBX_dev Would I be able to use this for a level system with stats and everything and making races, for example human, elf, etc if so can you tell me how and which ways I can practise this method
Levels and stats can be saved in the player class, so you can 100% use it for that. For your races, you can use something called inheritance on your player class, you can create separate classes which are names as your races then you can use inheritance to link the race class to your player class. Then you can put different functions and variables in your race class which corresponds to that class of race 👍
@@AshRBX_dev ok thanks but how would I call inheritance and would I do it in the same script is inheritance __.index? and also would I be able to make fighting styles for example you can learn different fighting styles from an npc if you already have one you can't get another
Have you gone into the settings => Security => and turned on allow roblox enable studio access to API services? This might fix your issue. If not, let me know and if you want further help join my discord server and DM me and I’ll help further
In the description, there should be paste bins that contain the completed code. If you are having issues, compare your line to the line in the paste bin code. There are bug fixes at the end that I mention so if you haven’t watched them, I would recommend watching the bug fixes chapter in the video. I made a mistake with the JSON and then changed in the chapter let me know if you have any more issues 👍