I’m currently working on a brand new project, however this is a major roadblock that I’ve been trying to fix for the past week. Honestly, I’m not the best at coding. This is actually from another project, but the datastores function correctly. When coping the code it wasn’t working, one of the issues that has been happening is the datastore isn’t saving the values. So, upon rejoining it believes that the data is ‘nil’ which brings me to my current output log. My plan for this script is to save leaderboard values, which I will also be using similar scripts for some of my other values that will not be displayed on the leaderboard. This script is to save three different leaderboard values, and unlike the developer hub shows, this script doesn’t autosave. Instead, it will load the data when a player joins (If there is any), then saves that data once the user leaves.
The warnings that are saying ‘Cannot load your ___ count!’ are intentional, as the game believes that no data exists for the player, but this error only occurs when the player enters the game for the first time (Working on fixing that). I have tried fixing my code as much as possible, but even while testing it the values are not saving. I have looked in the developer hub, but it doesn’t relate to my script. Here is what I have currently:
local DSS = game:GetService("DataStoreService")
local EssenceSave = DSS:GetDataStore("EssenceValueSave")
local MagicSave = DSS:GetDataStore("MagicValueSave")
local SoulSave = DSS:GetDataStore("SoulValueSave")
game.Players.PlayerAdded:Connect(function(player)
local leaderstats = Instance.new("Folder")
leaderstats.Name = "leaderstats"
leaderstats.Parent = player
local Essence = Instance.new("IntValue")
Essence.Name = "Essence"
Essence.Parent = leaderstats
local Magic = Instance.new("IntValue")
Magic.Name = "Magic"
Magic.Parent = leaderstats
local Soul = Instance.new("IntValue")
Soul.Name = "Soul"
Soul.Parent = leaderstats
local data = nil
local data2 = nil
local data3 = nil
local success, errormessage = pcall(function()
data = EssenceSave:GetAsync(player.UserId.."-Essence")
end)
local success2, errormessage = pcall(function()
data2 = MagicSave:GetAsync(player.UserId.."-Magic")
end)
local success3, errormessage = pcall(function()
data3 = SoulSave:GetAsync(player.UserId.."-Soul")
end)
if data ~= nil then
Essence.Value = data
else
print("Cannot load your essence count!")
warn(errormessage)
end
if data2 ~= nil then
Magic.Value = data2
else
print("Cannot load your magic count!")
warn(errormessage)
end
if data3 ~= nil then
Soul.Value = data3
else
print("Cannot load your soul count!")
warn(errormessage)
end
end)
game.Players.PlayerRemoving:Connect(function(player)
local success, errormessage = pcall(function()
EssenceSave:SetAsync(player.UserId.."-Essence",player.leaderstats.Essence.Value)
end)
local success2, errormessage = pcall(function()
MagicSave:SetAsync(player.UserId.."-Magic",player.leaderstats.Magic.Value)
end)
local success3, errormessage = pcall(function()
SoulSave:SetAsync(player.UserId.."-Soul",player.leaderstats.Soul.Value)
end)
if success then
else
print("Cannot save your essence count!")
warn(errormessage)
end
if success2 then
else
print("Cannot save your magic count!")
warn(errormessage)
end
if success3 then
else
print("Cannot save your soul count!")
warn(errormessage)
end
end)
If anyone could help me with this issue, please try. Also, instead of commenting a fixed script, can you please tell me what is wrong with it, so I can fix it in the future. Thank you!
Often datastores don’t work well in Studio. Have you tested this in the real game? Also how are you changing he leaderstats, through a script or through the properties tab?
UPDATE: I attempted to play in-game and it did successfully work inside. I believe something I should take into affect is joining the game first, as the datastore works in studio afterwards.
If you’re testing in studio then whenever you change a value and close the game, you’re actually just shutting down a server and PlayerRemoving has no time to fire. I recommend using something like a kick or just save the game and test on roblox and not on roblox studio. Another problem is that you might be saving your values on the client and not on the server, remember that the client cannot edit server values so if you’re changing it on the client, go in the Test tab and save your data through the server. Also make sure that API access is enabled through game settings. (I don’t recommend spamming pcalls around your script, just save your data using a table)
This is actually a very simple fix. When the server has one player and the player leaves, the server doesn’t have time to save the player’s data, because it instantly shuts down. There is a lil’ somethin’ called game:BindToClose(), which delays the server shutdown. Doing this will give your script enough time to save. (BTW, I recommend saving player data in a table, like in the example below because it might slow down datastore) Here is an example:
local dss = game:GetService("DataStoreService")
local playerData = dss:GetDataStore("PlayerData")
local function save(player)
local key = "Data_"..player.UserId
local s, f = pcall(function()
local leaderstats = player:WaitForChild("leaderstats")
playerData:UpdateAsync(key, function()
return {
Coins = leaderstats:WaitForChild("Coins").Value,
Points = leaderstats:WaitForChild("Points").Value
}
end)
end)
if not f then
print("Successfully saved "..player.Name.."'s Data ("..player.UserId.."). Key: "..key)
elseif f then
warn("Failed to save "..player.Name.."'s Data ("..player.UserId.."). Key: "..key..". Error: "..f)
end
end
game.Players.PlayerAdded:Connect(function(player)
local savedData = playerData:GetAsync("Data_"..player.UserId) or {}
local leaderstats = Instance.new("Folder", player)
leaderstats.Name = "leaderstats"
local coins = Instance.new("NumberValue", leaderstats)
coins.Name = "Coins"
coins.Value = savedData.Coins
local points = Instance.new("NumberValue", leaderstats)
points.Name = "Points"
points.Value = savedData.Points
end)
game.Players.PlayerRemoving:Connect(save)
game:BindToClose(function()
for i, v in pairs(game.Players:GetPlayers()) do
wait()
save(v)
end
end)
Yeah, instead of having 3 datastores you can use 1 single table.
--saving data
local statsTable = {}
statsTable.Essence = player.leaderstats.Essence.Value
statsTable.Magic = player.leaderstats.Magic.Value
statsTable.Soul = player.leaderstats.Soul.Value
mainDatastore:SetAsync(player.UserId, statsTable)
--calling data
local data
data = mainDatastore:GetAsync(player.UserId)
print(data)
print(data.Magic, data.Soul, data.Essence)
You can use only 1 pcall function and that is when you’re loading the data and saving the data, It’s not necessary however but people use it so that if the script errors, the pcall should print the error. Here is an example of how to save data using a table :
local MyData = {
IntValue = player.leaderstats["IntValue"].Value;
StringValue = player.leaderstats["StringValue"].Value;
}
local saved, error_ = pcall(function()
MyDataStore:SetAsync(**KEY**, MyData)
end)
and an example of how to load data using tables :
local loaded, error_ = pcall(function()
MyData = MyDataStore:GetAsync(**KEY**)
end)
if loaded then
IntValue.Value = MyData.IntValue
StringValue.Value = MyData.StringValue
print("Loaded data")
elseif error_ then
warn(error_)
end