Datastore script not working

I’m making a system to save weapon damage as part of an upgrade system for my game, for some strange reason, whenever I run this, it saves all of the data properly, but when I try and use GetAsync() it returns nil. Here’s the code:

local dataStoreService = game:GetService("DataStoreService")
local XPDataStore = dataStoreService:GetDataStore("XPDataStorage")
local upgradePointsStore = dataStoreService:GetDataStore("UpgradePoints")
local bowDamageStore = dataStoreService:GetDataStore("BowDamage")
local grapplerRangeStore = dataStoreService:GetDataStore("GrapplerRange")
local swordDamageStore = dataStoreService:GetDataStore("SwordDamage")
local gunDamageStore = dataStoreService:GetDataStore("GunDamage")
local playerData = {}


game.Players.PlayerAdded:Connect(function(player)
	local statsFolder = Instance.new("Folder")
	statsFolder.Name = "StatsFolder"
	statsFolder.Parent = player
	
	local xpValue = Instance.new("IntValue")
	xpValue.Parent = statsFolder
	xpValue.Name = "XP"
	
	local upgradePointsValue = Instance.new("IntValue")
	upgradePointsValue.Parent = statsFolder
	xpValue.Name = "UpgradePoints"
	
	local bowDamageValue = Instance.new("IntValue")
	bowDamageValue.Parent = statsFolder
	bowDamageValue.Name = "BowDamage"
	
	local grapplerRangeValue = Instance.new("IntValue")
	grapplerRangeValue.Parent = statsFolder
	grapplerRangeValue.Name = "GrapplerRange"
	
	local gunDamageValue = Instance.new("IntValue")
	gunDamageValue.Parent = statsFolder
	gunDamageValue.Name = "GunDamage"
	
	local swordDamageValue = Instance.new("IntValue")
	swordDamageValue.Parent = statsFolder
	swordDamageValue.Name = "SwordDamage"
	
	table.insert(playerData, #playerData + 1, {{player}})
	
	for i, v in pairs(statsFolder:GetChildren()) do
		if string.find(v.Name, "Damage") or string.find(v.Name, "Range") then
			table.insert(playerData[1], #playerData[1] + 1, v)
		end
	end
	
	local data
	local dataNew
	local bowData
	local grapplerData
	local gunData
	local swordData
	
	local success, errormessage = pcall(function()
		data = XPDataStore:GetAsync(player.UserId.."-XP")
	end)
	
	pcall(function()
		dataNew = upgradePointsStore:GetAsync(player.UserId.."-UpgradePoints")
	end)
	
	pcall(function()
		bowData = bowDamageStore:GetAsync(player.UserId.."-BowDamage")
	end)
	
	pcall(function()
		grapplerData = grapplerRangeStore:GetAsync(player.UserId.."-GrapplerRange")
	end)
	
	local success, errormessage = pcall(function()
		gunData = upgradePointsStore:GetAsync(player.UserId.."-GunDamage")
		print(player.UserId.."-GunDamage")
	end)
	
	print(success, errormessage)
	
	pcall(function()
		swordData = upgradePointsStore:GetAsync(player.UserId.."-SwordDamage")
	end)
	
	if dataNew then
		upgradePointsValue.Value = dataNew
	else
		upgradePointsValue.Value = 0
	end
	
	if bowData then
		bowDamageValue.Value = bowData
	else
		bowDamageValue.Value = 35
	end
	
	if grapplerData then
		grapplerRangeValue.Value = grapplerData
	else
		grapplerRangeValue.Value = 500
	end
	
	if gunData then
		gunDamageValue.Value = gunData
	else
		print("Gun data is nil")
		gunDamageValue.Value = 7
	end
	
	if swordData then
		swordDamageValue.Value = swordData
	else
		swordDamageValue.Value = 40
	end
	
	if data ~= nil then
		xpValue.Value = data
	else
		xpValue.Value = 0
	end
	
	xpValue.Name = "XP"
	upgradePointsValue.Name = "UpgradePoints"
end)

game.Players.PlayerRemoving:Connect(function(player)
	local xpValue = player.StatsFolder.XP
	local upgradePoints = player.StatsFolder.UpgradePoints
	
	pcall(function()
		XPDataStore:SetAsync(player.UserId.."-XP", xpValue.Value)
	end)
	
	pcall(function()
		upgradePointsStore:SetAsync(player.UserId.."-UpgradePoints", upgradePoints.Value)
	end)
	
	for index, v in pairs(playerData) do
		if v[1][1] == player then
			print("It's our player!")
			for i = 2, #v do
				local currentStore = dataStoreService:GetDataStore(v[i].Name)
				print(currentStore)
				local strings = player.UserId.."-"..v[i].Name
				print(strings)
				local otherthing = v[i].Value
				currentStore:SetAsync(strings, otherthing)
				print("Setting async")
			end
			table.remove(v, index)
		else
			print("Not rlly, it's actually "..tostring(v[1][1]).." So yeah lol")
		end
	end
end)

game:BindToClose(function()
	local players = game.Players:GetChildren()
	for i = 1, #players do
		if players[i] ~= nil then
			players[i]:Kick("This game is shutting down")
		end
	end
	
	wait(5)
end)

It doesn’t give me error, it simply prints nil for the gun data. If you need more info, tell me and I’ll respond.

Here is the output:
1469667980-GunDamage
true nil
Gun data is nil
Leaving:
Screenshot 2020-06-20 at 14.03.36

Which line returns nil? (30 chars)

I think you shall add succ and err to all pcall’s and do like

if not succ then
assert(false, err)
end

Also you shouldn’t have wait on BindToClose.

1 Like

I need it, because when I don’t add it, the game closes too fast for the script to save it.

1 Like

I already added a success and err before, it was successful

1 Like

use the get async in one pcall then it should work and the same for the set async

Oh, I’ll try that, but I don’t think that’s the problem, because before I added my table system, I saved the upgradepoints and XP in seperate pcalls and it worked.

Hold on! I know why! I used upgradepoints:GetAsync() :man_facepalming:

change it to one datastore because it is very inefficient

so your data doesnt get lost

1 Like

There is a limit to how much you can write to one data store

1 Like

Also, I’d add something else other than the wait. If server crashes, it won’t say “let me wait 5 secs and I’ll crash”.

1 Like

the 200K+ characters

the limit of datastores is 7 btw

1 Like

It’s not for crashing protection, it’s because if the player is the last one in the game and they leave, the script needs time to save their data.

1 Like

It shall be something with your DataStore because I never use waits and it works fine.

2 Likes

No, all tutorials have that, I’m not sure if you’re using datastore2 or something, but it won’t work without it for me. Alvinblox’s tutorial on youtube also has BindToClose

2 Likes