DataStore Works in Studio but not In-Game

I made a checkpoint script and datastore for the checkpoint script. The datastore saves and works fine when in Studio, but doesn’t work when I’m playing on ROBLOX. What am I doing wrong?

Script 1:

game.Players.PlayerAdded:Connect(function(Player)
	
	local leaderstats = Instance.new("Folder", Player)
	leaderstats.Name = "leaderstats"
	
	local Checkpoint = Instance.new("IntValue", leaderstats)
	Checkpoint.Name = "Checkpoint"
	Checkpoint.Value = 1
	
	Player.CharacterAdded:Connect(function(Character)
		
		repeat wait() until Player.Character ~= nil
		local checkpoint = workspace.Checkpoints:FindFirstChild(Checkpoint.Value)
		Character:WaitForChild("HumanoidRootPart").CFrame = CFrame.new(checkpoint.Position + Vector3.new(0,2,0))
		
	end)
	
end)

Script 2:

local DSS = game:GetService("DataStoreService")
local DS = DSS:GetDataStore("CheckpointDataStore") 

local function saveData(Player)

	local tableToSave = {
		Player:WaitForChild("leaderstats").Checkpoint.Value
	}

	local success, err = pcall(function()
		DS:SetAsync(Player.UserId, tableToSave)
	end)

	if success then
		print("Data has been saved!")
	else
		print("Data hasn't been saved!")
		warn(err)	
	end

end

game.Players.PlayerAdded:Connect(function(Player)
	
	local leaderstats = Player:WaitForChild("leaderstats")

	local Checkpoint = leaderstats:WaitForChild("Checkpoint")

	local data
	local success, err = pcall(function()

		data = DS:GetAsync(Player.UserId)

	end)

	if success then

		Checkpoint.Value = data[1]

	else
		print("The player has no data!") 
	end
	
end)

game.Players.PlayerRemoving:Connect(function(Player)
	saveData(Player)
end)

game:BindToClose(function() 
	for _, Player in pairs(game.Players:GetPlayers()) do
		saveData(Player) 
	end
end)
1 Like

Make sure that the API service is on in your game if not it will not save if it is on let me know!

1 Like

I did turn it on, which is why I find it weird that it saves in Studio but not in the game even though both have API service on.

1 Like

Like… why does it work in Studio without any errors but not when I actually play it on ROBLOX? It doesn’t make any sense.

1 Like

Well, guess this question died.

1 Like

I tested your code on studio and in game, and it worked fine on both. Whats exactly the problem you are having?
When I join the server I get teleported to the part named 1 or 2 or 3 depending on what was the last value I had on leaderstats, when I left the server, I got that value stored, and when I join the game I got teleported to that part

1 Like

When I play in-game, for example: I stepped on the 2nd checkpoint and my Checkpoint value became 2. Then I waited a bit, then left the game. Then when I join back I spawn at checkpoint 1.

1 Like

So… ROBLOX just hates me? :sob:

1 Like

The only thing I noticed is this
On the CharacterRemoved event, you are triggering the Save function to save the new value. In Studio I noticed that triggers 2 times, yielding the datastore due to many calls, the server received 2 calls to save the datastore at the same time for the same player. When the CharacterRemoved event occurs and when the game:BindToClose occurs for all the players.

So I get a yellow warning of many calls at the same time, gets queued then solved.
But thats the only thing that is not working fine, other than that, Im getting the values saved normally.

Are u sure you are changing the value correctly when the player touch the checkpoint part?
I changed the value by console script, cause I was lazy to make a touching part.

1 Like

This is the TouchHandler script:

local Checkpoints = script.Parent

for i,v in pairs(Checkpoints:GetChildren())do
	
	if v:IsA("BasePart") then
		v.Touched:Connect(function(hit)
			
			if hit.Parent:FindFirstChild("Humanoid") then
				local player = game.Players:GetPlayerFromCharacter(hit.Parent)
				if player then
					player.leaderstats.Checkpoint.Value = tonumber(v.Name)
				end
			end
			
		end)
	end
	
end

Well I used PlayerRemoving for when the player leaves the game and BindToClose for unexpected server shutdowns and the like.

1 Like

Yup, I know why you are using it. Unexpected server shutdown. And that error will not happen in game, only in studio, or when you leave a server that is totally empty (maybe)

Your touching code, seems to work fine. Let me test it again in-game

1 Like

Wait I just realized something, looking at this video, my checkpoint value was originally 2 then became 1

https://streamable.com/xbhfe3

1 Like

Like at 0:25 you can see the checkpoint value is 2 then becomes 1

1 Like

True!
The problem is that your character is maybe touching the part that is 1, when it initialize. Turning it to 1, no matter if you had 2 value

1 Like

I originally made this script so the player’s checkpoint couldn’t change back to checkpoints with lower values than the current one… let me see if adding that back might fix this problem.

1 Like

Another thing I noticed, is the second script. You are teleporting the player when joins, to the value you just created, instead of being sure if a datastore exist and use that value.
You should merge both scripts into one, and not having 2 different player.Joined events, that controls the same system

1 Like

Well, I did try to merge them together but they ended up not working… may try merging again later if this solution doesn’t pan out.

1 Like

I merged both scripts, and added a 5 times retry if the connection with the datastore fails, then checking if the datastore of that player its empty which means its a new player, so give value 1, if the datastore is not empty, take the value and set it.
Then TP the player to the corresponding position found. (I changed the name of the datastore, so you can test it as a new player that joins with an empty datastore)

local DSS = game:GetService("DataStoreService")
local DS = DSS:GetDataStore("CheckPointDS") 

local function saveData(Player)
	local tableToSave = {
		Player:WaitForChild("leaderstats").Checkpoint.Value
	}

	local success, err = pcall(function()
		DS:SetAsync(Player.UserId, tableToSave)
	end)

	if success then
		print("Data has been saved!")
	else
		print("Data hasn't been saved!")
		warn(err)	
	end
end

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

	local Checkpoint = Instance.new("IntValue", leaderstats)
	Checkpoint.Name = "Checkpoint"
	
	local success, data = pcall(function()
		return DS:GetAsync(Player.UserId)
	end)
	
	-- If the Datastore connection failed, retry 5 times
	if not success then
		print("no success first try, retrying")
		-- Retry holder count
		local retry = 0

		-- Retry 5 times with 1 second delay
		while retry < 5 do
			success, data = pcall(function()
				return DS:GetAsync(Player.UserId)
			end)

			-- If error happens
			if not success then
				wait(1)
			else
				print("datastore found on try: ", retry)
				break -- Break the thread continue with script
			end
		end
	end
	
	-- If Success of connection, check if value is empty or not
	-- Being empty means a new player, so give value 1
	if success then
		if data then
			print("Success")
			Checkpoint.Value = data[1]
		else
			-- If no error call and no data
			print("Table is empty means new player")
			Checkpoint.Value = 1
		end
	else
		print("EPIC Error")
		--[[ Teleport the player to another place, wait there a few seconds
		then teleport it back again into the main game to try again	]] 
	end
	
	Player.CharacterAdded:Connect(function(Character)
		repeat wait() until Player.Character ~= nil
		local checkpoint = workspace.Checkpoints:FindFirstChild(Checkpoint.Value)
		Character:WaitForChild("HumanoidRootPart").CFrame = CFrame.new(checkpoint.Position + Vector3.new(0,2,0))
	end)
end)

game.Players.PlayerRemoving:Connect(function(Player)
	print("onRemove")
	saveData(Player)
end)

game:BindToClose(function() 
	for _, Player in pairs(game.Players:GetPlayers()) do
		print(Player)
		saveData(Player) 
	end
end)

Theres no need to use any other script, just this one. Be sure to test it with the others script disabled

1 Like

Oh… I see what I did wrong now while I was trying to merge them together. :sweat_smile: Thank you so much for your help. :pray:

1 Like