Data saving not working properly

Recently, I tried making a data saving feature for my game, but after trying it out it just didn’t save. No error in the output. I’ve gone through my code countless times and I don’t see anything wrong with it, unless I’m missing something I have no clue about.

I don’t know how to fix this.

This is also on, by the way.
image

local DataStoreService = game:GetService("DataStoreService")
local playerData = DataStoreService:GetDataStore("PlayerData")

local function onPlayerJoin(player)
	local leaderstats = Instance.new("Folder",player)
	leaderstats.Name = "leaderstats"
	leaderstats.Parent = player
	
	local moneyStat = Instance.new("IntValue",leaderstats)
	moneyStat.Name = "Money"
	moneyStat.Parent = leaderstats
	
	local playerUserId = 'Player_'.. player.UserId
	local data = playerData:GetAsync(playerUserId)
	
	if data then
		moneyStat.Value = data
	else
		moneyStat.Value = 0
	end
end

local function onPlayerExit(player)
	print("Player left") --This runs, but the stuff below it doesn't??
	local success, err = pcall(function()
		local playerUserId = 'Player_'..player.UserId
		playerData:SetAsync(playerUserId, player.leaderstats.Money.Value)
	end)
	if not success then
		warn("Could not save data!") --This doesn't even appear.
	end
end

game.Players.PlayerAdded:Connect(onPlayerJoin)
game.Players.PlayerRemoving:Connect(onPlayerExit)
1 Like

you need to bind onPlayerExit to game:BindToClose instead i think

BindToClose() only gets triggered if the server is shutting down or the last player of the server leaves the game.

Where’s your protective call function? DataStores could fail occasionally so use a pcall function. It returns one value but store this in 2 variables.

local data
local success, failure = pcall(function()
    data = playerData:GetAsync(playerUserId)
end)

if success then
    Money.Value = data or 0 - - sets the value to 0 if the player first time joins the game.
else
    warn(“Failed to load data.”)
end

When SetAsync() on PlayerRemoving event, use protective call function as well as above. And try testing the DataStore in the actual game.

PlayerRemoving means the player is being removed from the service which includes all descendants of player which means leaderstat information as well. The SetAsync probably isn’t able to get the Money value fast enough before the player data was removed. I suggest storing the player’s info in a table so the script always has a reference even if the player leaves server, and then you can remove the reference when its no longer needed when their data has been saved.

Problem is, I do not know how to do that.

This didn’t work. It just comes up with this now.
image

EDIT: Now it doesn’t save. At all. No output error. It just doesn’t save or load.

Did you try testing it in your actual game? I said don’t test it in Studio, test it as a Roblox game.

I tested it as a roblox game many times, too.

Did you try making a part that whenever you click it, your money value gets increased, and leave the game and join back to see if it works or not?

That’s what already happens. Maybe it’s because I’m using a localscript? I tried using the exact same code that gives me the money in a serverscript, and it worked fine…

Lua’s weird. At least to me.

First of all, DataStore ONLY works in server scripts, not local scripts. Second, I think I know the problem, but I need to get the error code, so at the PlayerRemoving event, the part where it says warn(“Could not save data”), concatenate it with the error code so it will be:

warn(“Could not save data! Error code: “..err)

Oh. Right. Silly me. I should’ve expected local scripts to not work with this.

Also, the “could not save data error” no longer appears with a server script. So I can’t really get that for you, unless you want me to switch on over to the local script again for a bit.

It works as a server script though, saving and loading and all. So uh…

DO NOT USE LOCAL SCRIPT. DataStore is not replicated over the boundary of the servers if it’s from the client.

So I think I know the problem, when you SetAsync(), you need to provide a table or a dictionary when saving the data.

local tableToSave = {
    Money = player.leaderstats.Money.Value
    — add more here if you want, but make sure to save the key’s name correctly.
}

local success, err = pcall(function()
    playerDataStore:SetAsync(playerUserId,tableToSave)
end)

if success then
    print(“Saved data.”)
else
    print(err..”: unable to save data.”)
end

Then when you wanna load the data, do:

if data then
    moneyStat.Value = data.Money of 0
else
    warn(“Failed to load data.”)
end

You will notice the data.Money is the same as the key name in tableToSave, make sure you index the correct key name to load multiple data’s.

Using a table, I could also save multiple leaderboard values, right? I’ll experiment around with it and make a back-up of the script I have so far. Thanks for the help and sorry I’m such a bother with this! I’m learning, afterall.

Yes you can save multiple values using a table. But make sure it’s a dictionary, not an array.

1 Like

Nevermind. Back to square 1, my entire game broke with DataStores. Had to entirely get rid of the DataStore code. Any more help is appreciated.