Datastore Tutorial for Beginners

Hello.
I did this, and it works but seems a bit hardcoded as I must save as like 14 different items.
I tried to use for-loops to do this but it isn’t working.
Code:


-- // Assigning variables //
local DataStoreService = game:GetService("DataStoreService")
local dataStore = DataStoreService:GetDataStore("PlaneSkinOwnedSave") -- This can be changed to whatever you want

local function saveData(player) -- The functions that saves data
	local skins = player.OwnedSkins
	tableToSave = {
	}
	for i,v in pairs(skins:GetDescendants()) do
		if v.Name == "Owned" then
			table.insert(tableToSave, v.Value)
			print(v.Value)
		end
	end
	local success, err = pcall(function()
		dataStore:SetAsync(player.UserId, tableToSave) -- Save the data with the player UserId, and the table we wanna save
	end)

	if success then -- If the data has been saved
		print("Data has been saved!")
	else -- Else if the save failed
		print("Data hasn't been saved!")
		warn(err)		
	end
end
game.Players.PlayerAdded:Connect(function(player) -- When a player joins the game
	wait(1)
	-- // Assigning player stats //
	local skins = player.OwnedSkins
	local toGive = {}
	for i,v in pairs(skins:GetDescendants()) do
		if v.Name == "Owned" then
			table.insert(toGive, v.Value)
		end
	end
	local data -- We will define the data here so we can use it later, this data is the table we saved
	local success, err = pcall(function()
		data = dataStore:GetAsync(player.UserId) -- Get the data from the datastore
	end)
	if success and data then -- If there were no errors and player loaded the data
		for count = 1,14 do
			print(data[count])
			toGive[count] = data[count]
		end
	else -- The player didn't load in the data, and probably is a new player
		print("The player has no data!") -- The default will be set to 0
	end

end)
game.Players.PlayerRemoving:Connect(function(player) -- When a player leaves
	local success, err  = pcall(function()
		saveData(player) -- Save the data
	end)
	if success then
		print("Data has been saved")
	else
		print("Data has not been saved!")
	end
end)
game:BindToClose(function() -- When the server shuts down
	for _, player in pairs(game.Players:GetPlayers()) do -- Loop through all the players
		local success, err  = pcall(function()
			saveData(player) -- Save the data
		end)
		if success then
			print("Data has been saved")
		else
			print("Data has not been saved!")
		end
	end
end)

No errors in dev log

1 Like

Hi i tried using your datastore tutorial but whenever i leave the game it doesnt save the data. i didnt changed anything in the code. just added the values and another folder.

may i ask if how can i store a instance without need the player id like

i put a part in basepart

then i abandoned the server

then i went back the part is still in the basepart

how can i use datastore in there without needing a players key

You can use anything as the key which will be like accessing a lock with all of your information

Maybe you’re changing the values on the client side and not server

Extremely helpful and informative, thanks mate!

I also really appreciate the helpful comments and explanation for what each code segment does and why! Very helpful for newer scripters who may have no idea what each segment does.

As an extra side note by the way, in Part 2 for the final code at the top, the second to last ‘end’ still has a parenthesis even though it doesn’t need it.

game:BindToClose(function() – When the server shuts down
for _, player in pairs(game.Players:GetPlayers()) do
saveData(player) – Save the data
end)
end)

1 Like

What if I wanted to make a shop system with weapons, And it saves what ones you already own? Would I have to make them separate like

local Itemone = Instance.new("IntValue")
	Itemone.Name = "RustySword"
	Itemone.Parent = leaderstats

Or would I be able to do something like making the data ["Rusty Sword","Crossbow",,"Dark heart"] all in one string?

well you can do both, you can save everything into 1 string and then get the names by using string.split, or if you want to save it into 1 array then you can loop through each value for the savedWeapons

What a misinformed article lol. While it is obviously bad practice to use while wait() do in cases when a conditional could easily be substituted into the while statement (like the example provided in the doc), there are many cases like the example provided by @Urxpaly45 where it really doesn’t matter and— in fact— increases readability.

Acting as if someone is “a bad programmer” (as the article states) simply for following a certain convention— irrespective of the circumstances surrounding the use case— proves the only bad programmer is the one peddling this misinformation. And exposes their lack of critical thinking skills.

while wait() do is a tool in your coding arsenal. Good programmers know when to use it and when not to. Bad programmers read opinion and accept it as doctrine.

3 Likes

There’s not even a need to do any while wait statements. Just use RunService

RunService.Heartbeat:Connect(function()
    -- fires once every frame
    task.wait(1) -- add this to make it wait one second every frame before firing code
end)

This wouldn’t function, it would simply fire every frame because the task.wait does not debounce any events, the wait is useless

1 Like

Event listeners run in separate threads lol this wouldn’t function as intended.

1 Like

Would this be good to handle if data wasn’t loaded in? (Ex. There was an error loading data).

I changed the if & elseif statements to check for:

  • Success and data > load in the data.
  • Success but no data returned > set the players data to 0 (assuming they are a new player)
  • Otherwise if no success > Kick the player
	local data -- We will define the data here so we can use it later, this data is the table we saved
	local success, err = pcall(function()

		data = dataStore:GetAsync(player.UserId) -- Get the data from the datastore

	end)

	if success and data then -- If there were no errors and player loaded the data

		Rank.Value = data[1] -- Set the money to the first value of the table (data)
		Tokens.Value = data[2] -- Set the coins to the second value of the table (data)
	
	elseif success then -- The player didn't load in the data, and probably is a new player
		print("The player has no data!") -- The default will be set to 0
	else
		warn(err)
		player:Kick("Data loading error - check your connection & Roblox status")
	end
end)

Extremely helpful! Much more clearer, while also being shorter than a video or tutorial, great job!

1 Like

You don’t realize how helpful this is.

Thank you!

1 Like

If you want to save data safer and easier with less risk of data loss you should also look into learning a known datastore module like ProfileService or Suphis, even if you’re a beginner, when you learn it, you’re pretty much done.

It’s also less of a hassle than regular datastores and they have templates for player data!

2 Likes

Thanks!

But I’ll stick with the regular DataStore for now because ProfileService is a lot more complicated.

I may try Suphis tho.

1 Like

If you think ProfileService is complicated you probably won’t like Suphi’s either, but they are all pretty equal to learn as the normal datastores, just with different formats. I find it easier to stay away from the default datastore system because (i suck at it haha)

If you want, here’s my reccomended tutorials on ProfileService and SDM, SDM is more up-to-date so if you can and have the time, I’d suggest learning it, otherwise you can just stick with the default roblox datastore. One problem I have with the normal roblox datastore though is the lack of session locking.

1 Like

I’ll learn ProfileService when I have time. Thank you for that tutorial!

What is session locking? I haven’t learnt it and I don’t know how to use it.

Session locking is pretty complicated, but here’s the gist of it. Just read the “Why is session locking useful?” section. Basically prevents Item Duplication and Loading Old Data.

Also I’d (PERSONALLY) reccommend Suphi’s over ProfileService as they are pretty similar but Suphi’s is more modern.

1 Like