Not saving Data! [DataStore]

Hello… again!

Try changing

local data
local success,err = pcall(function()
	data = myData:GetAsync(plr.UserId)
end)

to

local success,data = pcall(function()
	return myData:GetAsync(plr.UserId.."Coins")
end)
1 Like

At first everything was fine, but again it does not work…

Did you add more to it? If so let me see whatever you changed.

local event = game.ReplicatedStorage:WaitForChild("coin")

local datastore = game:GetService("DataStoreService")

local myData = datastore:GetDataStore("myData")
--local GateData = datastore:GetDataStore("GateData")

game.Players.PlayerAdded:Connect(function(plr)
	local leaderstats = Instance.new("Folder",plr)
	leaderstats.Name = "leaderstats"
	
	local coins = Instance.new("IntValue",leaderstats)
	coins.Name = "Coins"
	
	local gate1 = Instance.new("BoolValue", plr)
	--gate1.Value = false
	gate1.Name = "Gate1"
		
	local success,data = pcall(function()  -- I CHANGE THIS
		return myData:GetAsync(plr.UserId.."Coins")
	end)
	
	if success then
		coins.Value = data
		--gate1.Value = data
	end
	
	local function clockTime()
		event:FireClient(plr)
		coins.Value += math.random(1,100)
	end
	
	while wait(25) do
		clockTime()
	end
end)

game.Players.PlayerRemoving:Connect(function(plr)
	local success,err = pcall(function()
		myData:SetAsync(plr.UserId.."Coins",plr.leaderstats.Coins.Value)
	end)
	if not success then
		warn(err)
	end
	local success,err = pcall(function()
		myData:SetAsync(plr.UserId.."Gate1",plr.Gate1.Value)
	end)
	if not success then
		warn(err)
	end
end)

What is the remote event in this doing?

Also, any errors or warns?

My current theory is you’re using :WaitForChild() which would be fine but it’s taking too long to find the child and by the time it finds it/gives up your player has already loaded but the function hasn’t, so it doesn’t run.

Every 25 seconds, the function is launched along with a remote event. The local script accepts and within 5 seconds the player runs faster than the previous speed.

Also no errors.

1 Like

Got it.

One last question, why is clocktime() a function? Couldn’t you just put the code in there in the while loop or do you need it as a function for future use?

It’s just an interest, I wanted to do that. But I don’t think it can be an error.

Not sure what you mean but I know the overall goal so here’s what I came up with.
first get rid of this line at the top:

local event = game.ReplicatedStorage:WaitForChild("coin")

then change

local function clockTime()
	game.ReplicatedStorage:WaitForChild("coin"):FireClient(plr)
	coins.Value += math.random(1,100)
end

while wait(25) do
	clockTime()
end

to

while task.wait(25) do
	game.ReplicatedStorage:WaitForChild("coin"):FireClient(plr)
	coins.Value += math.random(1,100)
end

This has a bit of a flaw though, we’re waiting 25 seconds AND the amount of time we wait for “coin”. If “coin” actually exists then this isn’t much of an issue because we’re only waiting a very small amount of extra time, but overall waiting can be a very small bit unreliable, if you wanted something more concrete you should look into RunService.

1 Like

I will definitely take a look at this service. But still, this will not solve the problem with preservation.

1 Like

Preservation of?

I’m a bit confused on the goal and problem

Data isn’t saved. But thanks for another helping.

1 Like

If you’re pressing the stop button in studio the data doesn’t save. Try leaving like you would a regular roblox game and see if it saves then.

1 Like

Yes, I forgot a little that the studio does not save data. Everything is good, works perfectly. But something Boolean is not preserved…

Maybe I’m not saving correctly when exiting?

1 Like

In your original code you have the boolean saving commented out.
Here’s the full script, everything should be working in it.

local datastore = game:GetService("DataStoreService")

local myData = datastore:GetDataStore("myData")

game.Players.PlayerAdded:Connect(function(plr)
	local leaderstats = Instance.new("Folder",plr)
	leaderstats.Name = "leaderstats"

	local coins = Instance.new("IntValue",leaderstats)
	coins.Name = "Coins"

	local gate1 = Instance.new("BoolValue", plr)
	gate1.Name = "Gate1"

	local success,data = pcall(function()  -- I CHANGE THIS
		return myData:GetAsync(plr.UserId.."Coins")
	end)
	if success then
		coins.Value = data
	end

	local success,data = pcall(function()  -- I CHANGE THIS
		return myData:GetAsync(plr.UserId.."Gate1")
	end)
	if success then
		gate1.Value = data
	end


	while task.wait(25) do
		game.ReplicatedStorage:WaitForChild("coin"):FireClient(plr)
		coins.Value += math.random(1,100)
	end
end)

game.Players.PlayerRemoving:Connect(function(plr)
	local success,err = pcall(function()
		myData:SetAsync(plr.UserId.."Coins",plr.leaderstats.Coins.Value)
	end)
	if not success then
		warn(err)
	end
	local success,err = pcall(function()
		myData:SetAsync(plr.UserId.."Gate1",plr.Gate1.Value)
	end)
	if not success then
		warn(err)
	end
end)

Double check that studio isn’t causing this issue because sometimes data doesn’t save through studio due to the server closing at the same time as the client when you end a play test.
I’ve recently had this issue and another way to solve it is by running a local server test with just one player and leaving the game but not closing the server and wait for it to save.

1 Like

Strangely, the Boolean is still not preserved.

change the value on the server-side

Value changing on the server script

A few notes to point out in your code:

  • Don’t use the 2nd parameter of Instance.new: It leads to some performance issues as explained in this official PSA. You should set the required properties other than the parent, then set the parent last

  • I would advise against saving the data in different keys as each request contributes to the request queue and will fill up the queue quickly so you end up getting errors as you’ve reached its limits. The best feature of DataStores is that you can store (serialisable) tables and considering that the data is associated with the player as stats, you can save all of the data in a table with one key

  • Nesting functions isn’t a great idea here, since every time a player joins, a new function is created and will eventually pile up as more and more players join. There is no reason for it to be in a function, since it isn’t being reused elsewhere. You should also stop the while loop if the player has disconnected

  • You can minimize data loss by implementing a forced save if the server is awaiting shut down and by implementing an auto save feature. Forced saved at shut down helps minimize data loss tremendously as this will require using game:BindToClose, which is a function that will call the callback/binded function and will wait for it to finish executing or at the very least, wait a minimum of 30 seconds, before the server shuts down due to there being no more players remaining or the developer forced shut down the servers. Autosaving helps too and I don’t mean saving the data as it changes, because that could reach the limits quickly but it depends, I mean saving it every few minutes.

Try this one out:

local event = game.ReplicatedStorage:WaitForChild("coin")

local players = game:GetService("Players")

local datastore = game:GetService("DataStoreService")

local myData = datastore:GetDataStore("myData")

-- Saves a specific player's data
function SaveData(player)
	local success, err = pcall(function()
		myData:SetAsync(player.UserId.."-data", {
			Coins = player.leaderstats.Coins.Value;
			Gate = player.leaderstats.Gate1.Value;
		})
	end)
	
	if not success then
		warn(err)
	end
end

players.PlayerAdded:Connect(function(plr)
	local leaderstats = Instance.new("Folder")
	leaderstats.Name = "leaderstats"
	leaderstats.Parent = plr

	local coins = Instance.new("IntValue")
	coins.Name = "Coins"
	coins.Parent = leaderstats

	local gate1 = Instance.new("BoolValue")
	gate1.Name = "Gate1"
	gate1.Value = leaderstats

	print("Boolean Status :",gate1.Value)

	local success, res = pcall(function()
		return myData:GetAsync(plr.UserId .. "-data")
	end)

	if success then
		coins.Value = res.Coins
		gate1.Value = res.Gate
	else
		warn(res)
	end

	while wait(25) do
		-- Terminate loop if the player disconnects
		if (not plr) then break end
		event:FireClient(plr)
		coins.Value += math.random(1,100)
	end
end)

players.PlayerRemoving:Connect(function(plr)
	SaveData(plr)
end)

-- Save all players' data when the server is supposed to shut down
game:BindToClose(function()
	for _, player in players:GetPlayers() do
		SaveData(player)
	end
end)