DataStore not working

Good day, I am looking forward to save some stats for my game, but they do not save.

local DataStoreService = game:GetService("DataStoreService")
local myDataStore = DataStoreService:GetDataStore("hellou123ndet")

local stats = {
	{"Coins", 100000},
	{"Items", 0},
	{"Inventory", nil}
}

game.Players.PlayerAdded:Connect(function(player)
	local folder = Instance.new("Folder")
	folder.Name = "stats"
	folder.Parent = player
	for i,v in pairs(stats) do
		local statType = "IntValue"
		local name = v[1]
		local value = v[2]
		if type(value) == "boolean" then
			statType = "BoolValue"
		elseif type(value) == "string" then
			statType = "StringValue"
		elseif value == nil then
			statType = "Folder"
		end
		local stat = Instance.new(statType)
		stat.Name = name
		if value then stat.Value = value end
		stat.Parent = folder
	end
	local data
	wait(1)
	local success, errormessage = pcall(function()
		myDataStore:SetAsync(player.UserId.."-coins", player.stats.Coins.Value)
		myDataStore:SetAsync(player.UserId.."-items", player.stats.Items.Value)
		myDataStore:SetAsync(player.UserId.."-invry", game:GetService("HttpService"):JSONEncode(player.stats.Inventory:GetChildren()))
	end)
end)

game.Players.PlayerRemoving:Connect(function(player)
	local success, errormessage = pcall(function()
		myDataStore:SetAsync(player.UserId.."-coins", player.stats.Coins.Value)
		myDataStore:SetAsync(player.UserId.."-items", player.stats.Items.Value)
		myDataStore:SetAsync(player.UserId.."-inventory", game:GetService("HttpService"):JSONEncode(player.stats.Inventory:GetChildren()))
	end)
	
	if success then
		print("saved")
	else
		print("error")
		print(errormessage)
	end
end)

This is the whole script. There are no more scripts. Thanks for watching, double thanks for those who reply.

Edit: I have enabled API.

2 Likes

Could we get a screenshot of the output?

1 Like

Above.

While waiting for you to supply that, there are two things to note. The first is that you are going to hit budget maximums pretty quickly with 3 DataStore calls per player per join state and you don’t even need that many DataStores when all of this can be done in one DataStore. The second is that JSONEncoding your data is unnecessary because it’s already done under the hood, so you’re only bloating the amount of characters you have already for the inventory key.

1 Like

From what I see based on my own testing, the DataStore is fine, and saving and loading data works well. Maybe you haven’t enabled Studio Access to API Services? It can be found in Game Settings > Options.

The method you are using isn’t a good method, it is better that you save data using a dictionary, something like

local data = {Coins = 0, Items = 0, Invetory = {}}

and save the table instead. There are more problems that include what happens in roblox. In studio specifically, the PlayerAdded event sometimes won’t fire when you join in PlaySolo. There is nothing wrong that you did, but the PlayerAdded event was set up after you joined the game, which would make it fail to fire. To fix this, you simply add a function to handle the players entrance, then use GetPlayers to give the Players currently in their data, like this

local function onPlayerAdded(plr)
	...
end

game.Players.PlayerAdded:Connect(onPlayerAdded)
for i, v in pairs(game.Players:GetPlayers()) do
	onPlayerAdded(v)
end

This will fix that problem, but there is another problem, if the last player leaves, then the PlayerRemoving event may not finish, the way to fix it is to use game:BindToClose(), but there would be a problem, game:BindToClose fires after PlayerRemoving, which would make a save twice, and lead to throttling, to fix this, you could use a variable called gameShutDown and set it to false, change it to true when the game is shutting down, like this

local gameShutDown = false
local function saveData(plr)
	...
end

game.Players.PlayerRemoving:Connect(function(plr)
	wait(0.1)
	if not gameShutDown then
		saveData(plr)
	end
end)

game:BindToClose(function()
	gameShutDown = true
	local numberOfPlayers = 0
	for i, v in ipairs(game.Players:GetPlayers()) do
		numberOfPlayers = numberOfPlayers + 1 -- we do this so we can use "spawn" and save multiple players data but not end the BindToClose before the data is saved
	end
	for i, v in ipairs(game.Players:GetPlayers()) do
		spawn(function()
			saveData(v)
			numberOfPlayers = numberOfPlayers - 1
		end)
	end
	while numberOfPlayers > 0 do wait(0.1) end
end)

Note that I used a spawn function, this is so that we save multiple players data at once, though, you could use coroutine.wrap(someFunction)() if you wanted to

Also note that roblox automatically encodes the value, so you don’t have use HttpService:JSONEncode() or HttpService:JSONDecode()