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)
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
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.
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.
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
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
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.
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
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