Hello! My data is not saving, (or loading?) even though it prints MyName's data was saved successfully.
Bit of context: I want to save a PlayerGui displaying the number of coins they have, so whenever the local script detects when the player’s leaderstat is being changed, it adds the coins and sends a remote event signal to the server to pick up.
Then, the server script picks it up and changes the IntValue that it is being parented in into the number of coins that they earned. Then there is another script, called "CoinSaving"
that the IntValue is being parented in.
The CoinSaving script is directly from a tutorial but with some modifications so it only saves the Coins IntValue.
There are no errors, it prints everything, but it just doesn’t seem to save (or load).
If anyone can figure this out, I would really appreciate it!
--Coin saving script [LONG].
local playerService = game:GetService("Players")
local dataStoreService = game:GetService("DataStoreService")
-- You can replace the "Data" in the brackets with anything you'd like.
-- It is the name of the data store
local gameDataStore = dataStoreService:GetDataStore("CoinsDataStore")
local function serialiseData(player)
-- Collects a player's data into a table
-- Find the player's leaderstats/playerstats
local playerstats = player:FindFirstChild("playerstats")
if not (playerstats) then
warn("No leaderstats/playerstats found for " .. player.Name)
return
end
-- Create a table for the data to go in
local data = {
Coins = playerstats.Coins.Value;
-- Because 'SpawnPoint' is a vector3 value which can't be saved,
-- we need to convert it to a dictionary
DataId = playerstats.DataId.Value;
}
return data -- This data can now be saved to a DatastoreService
end
local function deserialiseData(data)
end
local function saveData(player)
-- First we need to find their leaderstats / playerstats
local playerstats = player:FindFirstChild("playerstats")
if not (playerstats) then
-- Warn the script
return false, "No playerstats found for " .. player.Name
end
-- Next, serialise the data into a saveable format
local data = serialiseData(player)
-- Get their userId
local userId = player.UserId
-- Now we can attempt to save to Roblox
-- We retry up to 10 times if something goes wrong
local attemptsLeft = 10
local success, errorMessage
repeat wait()
pcall(function()
-- We should use UpdateAsync here instead of
-- SetAsync() as we can compare to previous data
success, errorMessage = gameDataStore:UpdateAsync(userId, function(old)
if not (old and old.DataId) then
-- If no old data was found, we should overwrite the data
return data
elseif (old.DataId > data.DataId) then
-- The data didn't load correctly! Do not overwrite
error("Data did not load correctly!")
else
-- The data is safe to overwrite
return data
end
end)
end)
attemptsLeft -= 1 -- Decrease the number of attempts left
until (attemptsLeft == 0) or (success)
-- Check that the data was saved
if success then
print(player.Name .. "'s data was saved successfully!")
-- We should increment their data Id so that their data
-- can be saved again in this server
playerstats.DataId.Value += 1
else
-- Display the error message
warn(player.Name .. "'s data wasn't saved! :", errorMessage)
end
-- Return the result
return success, errorMessage
end
local function loadData(player)
-- Get their user Id
local userId = player.UserId
local data = nil
local attemptsLeft = 10
-- Repeat 10 times, or until the script has communicated successfully
local success, errorMessage
repeat task.wait()
success, errorMessage = pcall(function()
data = gameDataStore:GetAsync(userId)
end)
attemptsLeft -= 1 -- Reduce the number of attempts left
until (attemptsLeft == 0) or success
-- Check if there was a problem with the Roblox servers
if (not success) then
warn("Error Loading player data:", errorMessage)
return
end
-- Check whether there is any data or they're a new player
-- Also, we should get their leaderstats and playerstats folders
local playerstats = player:WaitForChild("playerstats")
if data then
-- Returning player
-- Here we can load in the values
playerstats.Coins.Value = data.Coins or 0
-- Set their data Id to what it previously was
playerstats.DataId.Value = data.DataId or 0
else
-- New player!
-- Here we can set default values e.g cash = 50
playerstats.Coins.Value = 0
end
-- Finally we want to increment their dataId, to indicate that the data loaded
playerstats.DataId.Value += 1
return true -- Success!
end
-- This will run when a player joins the game.
local function onPlayerAdded(player)
-- Clone a playerstats folder
local playerstats = script.playerstats:Clone()
playerstats.Parent = player
-- **Load their data**
loadData(player)
end
-- This will run when a player leaves the game
local function onPlayerRemove(player)
-- Save their data
saveData(player)
end
-- This function will run when the script loads
local function initialise()
--[[ Here, we want to iterate through all players that
may have joined before this script loaded.
]]--
for _, player in ipairs(playerService:GetPlayers()) do
onPlayerAdded(player)
end
end
-- Connect events for when players leave / join
playerService.PlayerAdded:Connect(onPlayerAdded)
playerService.PlayerRemoving:Connect(onPlayerRemove)
game:BindToClose(function() -- Runs when a server shuts down
-- Iterate through every player in the server and save their data
for _, p in ipairs(playerService:GetPlayers()) do
saveData(p)
end
end)