My DataStore wont save

I am making a simple DataStore that saves you money in leaderstats. It isn’t saving for some reason but it is loading fine and I can’t work out why.

Here is the code:
Server Script in ServerScriptService:

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Remotes = ReplicatedStorage:WaitForChild("Remotes")
local DataStoreService = game:GetService("DataStoreService")
local DataStore = DataStoreService:GetDataStore("StatsSave")

local DefultData = {
	Money = 100;	
}
-- Load Data
game.Players.PlayerAdded:Connect(function(Player)
	local leaderstats = Instance.new("Folder")
	leaderstats.Name = "leaderstats"
	leaderstats.Parent = Player
	
	local Money = Instance.new("IntValue")
	Money.Name = "Money"
	Money.Parent = leaderstats
	
	local Data = DataStore:GetAsync(Player.UserId)
	
	if Data then
		Money.Value = Data
	else
		Money.Value = DefultData.Money
	end

end)

-- Save Data
local function SaveData(Player)
	local Money = Remotes.MoneySave:InvokeClient(Player)
	DataStore:SetAsync(Player.UserId, Money)
end

game.Players.PlayerRemoving:Connect(SaveData)

LocalScript in StarterPlayerScripts:

local leaderstats = script.Parent.Parent:WaitForChild("leaderstats")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Remotes = ReplicatedStorage:WaitForChild("Remotes")

local function SendData()
	return leaderstats.Money.Value
end

Remotes.MoneySave.OnClientInvoke = SendData

I have a RemoteFunction in ReplicatedStorage in a folder called Remotes and the RemoteFunction is called MoneySave.

Note:I have Studio API Services turned on and I get no errors.

Thank you in advanced.

3 Likes

I think SaveData won’t work because you’re waiting for the client to respond, but they’re already leaving the game (since you’re using PlayerRemoving and using InvokeClient).

Also a side note, I don’t think it’s a good idea to allow the client to send information to the server which it can manipulate.

Edit: You are using GetAsync and SetAsync correctly.

3 Likes

Yeah going on what someonedie said dont let the client send information back to the server and just find that information on the server, same with that the player is already leaving and all scripts mostly yield when a player leaves.

1 Like

I have tried doing this now and it still doesn’t want to save:

local function SaveData(Player)
	local Money = Player.leaderstats.Money.Value
	DataStore:SetAsync(Player.UserId, Money)
end

game.Players.PlayerRemoving:Connect(SaveData)
1 Like

Are you sure its loading the data correctly because it may be saving correctly but the data isn’t being loaded correctly when the player joins

How are you testing if it works or not?

1 Like

Instead of doing

local function SaveData(Player)
	local Money = Player.leaderstats.Money.Value
	DataStore:SetAsync(Player.UserId, Money)
end

game.Players.PlayerRemoving:Connect(SaveData)

I just done:

local function SaveData(Player)
	DataStore:SetAsync(Player.UserId, 1000) -- The 1000 is the users money
end

game.Players.PlayerRemoving:Connect(SaveData)

1 Like

Sorry, I mean how are you testing if the data works. Are you in Studio using the Player1 thingy simulation or have you made a new live baseplate?

Oh, I have tested it in studio and in a live baseplate.

Is this a game or just a save file and if it is a game does it have the API Service enabled

image

1 Like

It has Studio API Services enabled.

Hm maybe instead of the datastore saving place being the userId make it like

“player_UserIDHere” that way its a string not an int value

image
I dont think so, Doesn’t say array

You can set the second parameter to any variant, I’m positive about that (just not nil or an instance).

local function SaveData(Player)
    local Money = Player.leaderstats.Money.Value
    DataStore:SetAsync("player_"..Player.UserId, Money)
end

game.Players.PlayerRemoving:Connect(SaveData)

Okay so this should work

It states on the wiki that the first piece of data has to be a string so just Player.UserId wouldn’t work. Also for loading data make sure you add in “player_” before the UserID thing

2 Likes
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Remotes = ReplicatedStorage:WaitForChild("Remotes")
local DataStoreService = game:GetService("DataStoreService")
local DataStore = DataStoreService:GetDataStore("StatsSave")

local DefultData = {
	Money = 100;	
}
-- Load Data
game.Players.PlayerAdded:Connect(function(Player)
	local leaderstats = Instance.new("Folder")
	leaderstats.Name = "leaderstats"
	leaderstats.Parent = Player
	
	local Money = Instance.new("IntValue")
	Money.Name = "Money"
	Money.Parent = leaderstats
	
	local Data = DataStore:GetAsync(tostring(Player.UserId))
	
	if Data then
		Money.Value = Data
	else
		Money.Value = DefultData.Money
	end

end)

-- Save Data
local function SaveData(Player)
	local Money = Player.leaderstats.Money.Value
	DataStore:SetAsync(tostring(Player.UserId), Money)
end

game.Players.PlayerRemoving:Connect(SaveData)

Use “tostring()” on the key. The SetAsync and GetAsync (Along with UpdateAsync and IncrementAsync, etc) use strings for their keys. The value on the other hand can be a Variant of any type.

7 Likes