Data Save Script Won't Work (I figured it out)

I made a script to save the data of a players leaderboard stats. Though it only saves the first time they play. Lets say I join the game and get 30 coins. When I leave and rejoin I get another 5 coins. When I rejoin again it says I have 30. The script correlates with my leaderstats script so I’ll place both of my scripts in here.

Save data Script:

local DS = game:GetService("DataStoreService"):GetDataStore('SaveData')
game.Players.PlayerAdded:Connect(function(plr)
	wait()
	local plrkey = "id_"..plr.userId
	local save1 = plr.leaderstats.Souls
	local save2 = plr.leaderstats.Coins
	
	local GetSaved = DS:GetAsync(plrkey)
	if GetSaved then
		save1.Value = GetSaved[1]
		save2.Value = GetSaved[2]
	else
		local NumberForSaving={save1.Value, save2.Value}
		DS:GetAsync(plrkey, NumberForSaving)
	end
end)

game.Players.PlayerRemoving:Connect(function(plr)
	DS:SetAsync("id_"..plr.userId, {plr.leaderstats.Souls.Value, plr.leaderstats.Coins.Value})
end)

leaderstats script:

game.Players.PlayerAdded:Connect(function(player)
	local stats = Instance.new("Folder")
	stats.Name = "leaderstats"
	stats.Parent = player
	
	local souls = Instance.new("IntValue")
	souls.Name = "Souls"
	souls.Value = 0
	souls.Parent = stats
	
	local coins = Instance.new("IntValue")
	coins.Name = "Coins"
	coins.Value = 0
	coins.Parent = stats
end)

Both scripts are parented to ServerScriptService

1 Like

I recommend two things

  1. combine the datastore script and leaderstats script into one script
  2. add a BindToClose event

EDIT: also you should use UpdateAsync instead of SetAsync

2 Likes

So like this?

local DS = game:GetService("DataStoreService"):GetDataStore('SaveData')
game.Players.PlayerAdded:Connect(function(plr)
	wait()
	local plrkey = "id_"..plr.userId
	local save1 = plr.leaderstats.Souls
	local save2 = plr.leaderstats.Coins
	
	local GetSaved = DS:GetAsync(plrkey)
	if GetSaved then
		save1.Value = GetSaved[1]
		save2.Value = GetSaved[2]
	else
		local NumberForSaving={save1.Value, save2.Value}
		DS:GetAsync(plrkey, NumberForSaving)
	end
end)



game.Players.PlayerRemoving:Connect(function(plr)
	DS:UpdateAsync("id_"..plr.userId, {plr.leaderstats.Souls.Value, plr.leaderstats.Coins.Value})
end)

game.Players.PlayerAdded:Connect(function(player)
	local stats = Instance.new("Folder")
	stats.Name = "leaderstats"
	stats.Parent = player

	local souls = Instance.new("IntValue")
	souls.Name = "Souls"
	souls.Value = 0
	souls.Parent = stats

	local coins = Instance.new("IntValue")
	coins.Name = "Coins"
	coins.Value = 0
	coins.Parent = stats
end)

Then where would I implement the BindToClose event?

you would need to combine the two PlayerAdded events and the BindToClose would go under the PlayerRemoving function
BindToClose runs 30 seconds before the game closes

2 Likes

But how do i do that? Sorry I’m a bit stressed on this whole thing because how important save data is.

Alright I wrote up this, does it make sense?

local DS = game:GetService("DataStoreService"):GetDataStore('SaveData')
local Players = game:GetService("Players")
local DataStoreService = game:GetService("DataStoreService")
local RunService = game:GetService("RunService")
local playerData = {
	-- [UserId] = data
}
local dataStore = DataStoreService:GetDataStore("Data")
game.Players.PlayerAdded:Connect(function(plr)
	wait()
	local plrkey = "id_"..plr.userId
	local save1 = plr.leaderstats.Souls
	local save2 = plr.leaderstats.Coins
	
	local GetSaved = DS:GetAsync(plrkey)
	if GetSaved then
		save1.Value = GetSaved[1]
		save2.Value = GetSaved[2]
	else
		local NumberForSaving={save1.Value, save2.Value}
		DS:GetAsync(plrkey, NumberForSaving)
	end
end)


game.Players.PlayerAdded:Connect(function(player)
	local stats = Instance.new("Folder")
	stats.Name = "leaderstats"
	stats.Parent = player

	local souls = Instance.new("IntValue")
	souls.Name = "Souls"
	souls.Value = 0
	souls.Parent = stats

	local coins = Instance.new("IntValue")
	coins.Name = "Coins"
	coins.Value = 0
	coins.Parent = stats
end)

game.Players.PlayerRemoving:Connect(function(plr)
	DS:UpdateAsync("id_"..plr.userId, {plr.leaderstats.Souls.Value, plr.leaderstats.Coins.Value})
end)
game:BindToClose(function()
	-- if the current session is studio, do nothing
	if RunService:IsStudio() then
		return
	end
	print("saving player data")

	-- go through all players, saving their data
	local players = Players:GetPlayers()
	for _, player in pairs(players) do
		local userId = player.UserId
		local data = playerData[userId]
		if data then
			-- wrap in pcall to handle any errors
			local success, result = pcall(function()
				-- SetAsync yields so will stall shutdown
				dataStore:SetAsync(userId, data)
			end)
			if not success then
				warn(result)
			end    
		end
	end

	print("completed saving player data")

end)

i do this:

local datastore = game:GetService("DataStoreService"):GetDataStore("data")

game.Players.PlayerAdded:Connect(function(player)
	local leaderstats = Instance.new("Folder")
	leaderstats.Parent = player
	leaderstats.Name = "leaderstats"
	
	local soul = Instance.new("NumberValue")
	soul.Parent = leaderstats
	soul.Name = "Souls"
	
	local coin = Instance.new("NumberValue")
	coin.Parent = leaderstats
	coin.Name = "Coins"
	
	local debounce = Instance.new("BoolValue")
	debounce.Value = false
	debounce.Name = "Debounce"
	debounce.Parent = player
	
	local key = "user-" .. player.userId
	
	local storeditems = datastore:GetAsync(key)

	if storeditems then
		soul.Value = storeditems[1]
		coin.Value = storeditems[2]
	else
		local items = {soul.Value, coin.Value}
		datastore:SetAsync(key, items)
	end
end)

game.Players.PlayerRemoving:connect(function(player)
	local items = {player.leaderstats.Souls.Value, player.leaderstats.Coins.Value}
	local key = "user-" .. player.userId
	
	datastore:SetAsync(key, items)
end)

It doesn’t work, there are no error messages or things underlined in red

did you turn on api services in game settings?

Yes it is


well i dont know then try messing with some stuff

Got any ideas on what may be wrong with it? In the meantime i’ll mess around with it.

I actually figured it out, I changed the script a bit. Thanks for the help!!!

1 Like

you forgot to add a BindToClose event

2 Likes