You should probably put the “playerremoving” function ouside the the “playeradded” function. Also the player might not safe because the server closes before playerremoving gets called so add a “game:BindToClose()” to your script and save when the server closes or you could just use a “task.wait(3)” so “playerremoved” before the server closes.
I guess the problem is all related to the PlayerRemoving event. Basically you’re not using the SetAsync correctly.
The problem with this is that you’re not assigning the new data to their ‘Checkpoint’ datastore. When you do “Checkpoint.Value”, you’re just adding a new value to their server leaderstats, BUT not saving it!, you should do:
game.Players.PlayerRemoving:Connect(function(player)
local success, Checkpoints = pcall(function()
return PlayerCheckpoint:GetAsync(player.UserId)
end)
if sucess then
-- 'Checkpoints' in the pcall will be nil If the player doesn't have data.
local PlayerCurrentCheckpoint = player.leaderstats:FindFirstChild("Checkpoint").Value
PlayerCheckpoint:SetAsync(player.UserId, PlayerCurrentCheckpoint)
end
end)
And also, as @aron01224 said, put the PlayerRemoving event outside the PlayerAdded. By the way, I recommend to you simplify your script; Starting from the Touched event could be in another script.
And If possible, save the Checkpoint.Value to the Checkpoint data instantly when their data in the leaderstats changed. This means that it’s not necessary to save the player data when he left the game with the ‘PlayerRemoving’, because their Checkpoint will be instantly save at the moment of getting a new.
And, to load their data when he join to the game, you should do:
local success, PlayerCurrentCheckpointSaved = pcall(function()
return PlayerCheckpoint:GetAsync(player.UserId)
end)
if PlayerCurrentCheckpointSaved == nil then
warn("The data of this player is empty. Happens if the player join to the game first time.")
Checkpoint.Value = 0
else
Checkpoint.Value = PlayerCurrentCheckpointSaved
end
Remember to put this in the PlayerAdded event and after when you create all related to the leaderstats folder.
i can’t believe I forgot that part. There’s nothing in the output, even when I step onto another checkpoint to update the character’s leaderstat. Then when I rejoin, I start at spawn.
hello! thanks for the insight into my problem. i’ve updated the script yet it isn’t saving data whenever I leave.
local PlayerCheckpoint = DataStoreService:GetDataStore("Checkpoint")
game.Players.PlayerAdded:Connect(function(player)
local leaderstats = Instance.new("Folder")
leaderstats.Parent = player
leaderstats.Name = "leaderstats"
local Checkpoint = Instance.new("IntValue")
Checkpoint.Parent = leaderstats
Checkpoint.Value = 0
Checkpoint.Name = "Checkpoint"
local checkpoints = workspace.Obby.Checkpoints
for checkpoint = 1, #checkpoints:GetChildren() do
checkpoints[checkpoint].Touched:Connect(function(touch)
Checkpoint.Value = checkpoint
end)
end
local success, PlayerCurrentCheckpointSaved = pcall(function()
return PlayerCheckpoint:GetAsync(player.UserId)
end)
if PlayerCurrentCheckpointSaved == nil then
warn("The data of this player is empty. Happens if the player join to the game first time.")
Checkpoint.Value = 0
else
Checkpoint.Value = PlayerCurrentCheckpointSaved
end
end)
game.Players.PlayerRemoving:Connect(function(player)
local success, Checkpoints = pcall(function()
return PlayerCheckpoint:GetAsync(player.UserId)
end)
if success then
local PlayerCurrentCheckpoint = player.leaderstats:FindFirstChild("Checkpoint").Value
PlayerCheckpoint:SetAsync(player.UserId, PlayerCurrentCheckpoint)
print("Data saved before leaving")
end
end)
Here’s what the script currently looks like. I put a print statement in the PlayerRemoving event to ensure that data is being saved when the player leaves, but that doesn’t print. The warning message in the PlayerAdded event does print, though.
game:BindToClose(function()
for _, player in pairs(game.Players:GetPlayers()) do
--save the data, maybe try making a function to do so in order to be more efficient.
end
end)
Maybe try changing your function names in order to be more efficient.
local function loadData(player)
--loading code here
end
local function saveData(player)
--saving code here
end
game.Players.PlayerAdded:Connect(loadData)
game.Players.PlayerAdded:Connect(saveData)
game:BindToClose(function()
if game["Run Service"]:IsStudio() then task.wait(5) return end --PlayerRemoving will fire in studio testing
for _, player in pairs(game.Players:GetPlayers()) do --save every player's data
saveData(player)
end
end)
The BindToClose()function will run any provided code before the game shuts down.
The problem could simply be that the game shuts down before it has time to save the data, which this should fix.
local DataStoreService = game:GetService("DataStoreService")
local PlayerCheckpoint = DataStoreService:GetDataStore("Checkpoint")
local PlayersService = game:GetService("Players")
local ObbyCheckpoints = game:GetService("Workspace").Obby.Checkpoints
PlayerService.PlayerAdded:Connect(function(Player)
local leaderstats = Instance.new("Folder")
leaderstats.Parent = player
leaderstats.Name = "leaderstats"
local Checkpoint = Instance.new("IntValue")
Checkpoint.Parent = leaderstats
Checkpoint.Name = "Checkpoint"
local suc, PlayerCurrentCheckpoint = pcall(function()
return PlayerCheckpoint:GetAsync(Player.UserId)
end)
if PlayerCurrentCheckpoint ~= 0 then
Checkpoint.Value = PlayerCurrentCheckpoint
print("Player checkpoints loaded: ", Checkpoint.Value)
else -- "Nil" or 0 as default.
Checkpoint.Value = 0
end
end)
for i, Checkpoints in pairs(ObbyCheckpoints:GetChildren()) do
Checkpoints.Touched:Connect(function(touch)
local Player = PlayersService:GetPlayerFromCharacter(touch.Parent)
local Checkpoint = Player.leaderstats:FindFirstChild("Checkpoint")
Checkpoint.Value += 1
PlayerCheckpoint:SetAsync(Player.UserId, Checkpoint.Value)
print("Saving player checkpoints!")
end)
end
This allow you to load the player when PlayerAdded. And also, If the player get a new checkpoint, their data will be automatically save in the Checkpoints datastore. This allows you to avoid having to do the PlayerRemoving event.