So I’ve got a folder of the values, all the values are the same as what is shown in the folderChildren table below. I have it print out the values when the script detects a new player, and when the player leaves.
When the save runs, it prints out the new values. In this case lets say Stars is 130,000. When loading it appears to load an old value of 115,000. Everytime I leave, the script prints out the new value, yet when I load the game again, it loads the old value of 115,000. Any idea what’s wrong here? I’m testing repeatedly in studio.
local DataStore = game:GetService("DataStoreService"):GetDataStore("FolderDataTest")
local folderChildren = {
"Stars",
"Item1",
"Item2",
"Item3",
"Item4",
"Item5",
"Item6",
"Item7",
"Item8",
"Item9",
"Pet1",
"Pet2",
"Powerup1",
"Powerup2",
"Powerup3",
"Powerup4",
"Powerup5",
"Powerup6",
"Powerup7",
"Powerup8"
}
game.Players.PlayerAdded:Connect(function(player)
local newFolder = script:WaitForChild("PlayerData"):Clone()
newFolder.Parent = player
local folder = player:WaitForChild("PlayerData")
local savedValues = DataStore:GetAsync("FolderValues") or "New"
if savedValues == "New" then
print(player.Name.." has started the aventure!")
else
for _, child in ipairs(folder:GetChildren()) do
for i, childName in ipairs(folderChildren) do
if child.Name == childName then
child.Value = savedValues[i]
print(child.Value)
break
end
end
end
end
end)
game.Players.PlayerRemoving:Connect(function(player)
local folder = player.PlayerData
local values = {}
for _, child in ipairs(folder:GetChildren()) do
for i, childName in ipairs(folderChildren) do
if child.Name == childName then
values[i] = child.Value
print(child.Value)
break
end
end
end
DataStore:SetAsync("FolderValues", values)
end)
– save2 (is never printed when this fails) any idea why this is happening?
game.Players.PlayerRemoving:Connect(function(player)
local folder = player.PlayerData
local values = {}
for _, child in ipairs(folder:GetChildren()) do
for i, childName in ipairs(folderChildren) do
if child.Name == childName then
values[i] = child.Value
print(child.Value)
break
end
end
end
print("save1")
DataStore:SetAsync("FolderValues", values)
print("save2")
end)
You have many issues in that script. By not using pcall to handle the loading, you are possibly overwritting the starter values. (this will happen in real server, not in studio (not by normal means))
You are double looping when its not needed too.
I disabled some lines in your script and added some stuff, test it. Still the first issue I mentioned I did not fixed it.
This is assuming that the folder PlayerData you are cloning and placing in Player already contains the values you want with names etc.
local DataStore = game:GetService("DataStoreService"):GetDataStore("FolderDataTest")
game.Players.PlayerAdded:Connect(function(player)
local newFolder = script:WaitForChild("PlayerData"):Clone()
newFolder.Parent = player
--local folder = player:WaitForChild("PlayerData")
local savedValues = DataStore:GetAsync("FolderValues") or "New"
if savedValues == "New" then
print(player.Name.." has started the aventure!")
else
--[[
for _, child in ipairs(folder:GetChildren()) do
for i, childName in ipairs(folderChildren) do
if child.Name == childName then
child.Value = savedValues[i]
print(child.Value)
break
end
end
end
]]
print(savedValues)
for ValName, Val in pairs(savedValues) do
if newFolder:FindFirstChild(ValName) then
newFolder:FindFirstChild(ValName).Value = Val
end
end
end
end)
game.Players.PlayerRemoving:Connect(function(player)
local folder = player.PlayerData
local values = {}
--[[
for _, child in ipairs(folder:GetChildren()) do
for i, childName in ipairs(folderChildren) do
if child.Name == childName then
values[i] = child.Value
print(child.Value)
break
end
end
end
]]
for _, Val in pairs(player:FindFirstChild("PlayerData")) do -- set it to the folder of values in player
print(Val.Name, Val.Value)
values[Val.Name] = Val.Value
end
warn(values)
DataStore:SetAsync("FolderValues", values)
end)
The reason I had the table of names, and the loops was because the values might not be in the same order, loading and saving. At least that’s my theory, the values might not load in the correct order.
When player joins, you get the datastore. Iterate that datastore, and find the values in player that match with the key of the table(ds), update them, thats all.
If theres 30 keys in table, then it will repeat 30 times, each time you use the name of the key, which could be “Stars”, in player folder you find a value with a name “Stars”, and update its value.
Same on saving, you iterate the player folder, find 30 values, once per value you create a new key in table using the name of value as key, and insert the value into that key, after 30 iterations you have a table with 30 keys, with name and its values, thats what you wanna save in datastore.
When player joins, they have that table in datastore, iterate it etc
Look, I tested the script, and after creating a folder with random values using the names you provided, I tested the script, and my prints are correct:
I created a new data store and same issue happens. Like if I keep doing this over and over. It will eventually not work and load properly. Or maybe it’s not saving I’m not sure. I’ll create a video demonstrating. Give me a couple mins.
As shown here. I start with 50,000 which is loaded. I then increase that to 75,000. And I leave game. The table shows 75,000. When I load, it show’s and loads 50,000
This is the script:
– I renamed the data store → “FolderDataTest2”
local DataStore = game:GetService("DataStoreService"):GetDataStore("FolderDataTest2")
game.Players.PlayerAdded:Connect(function(player)
local newFolder = script:WaitForChild("PlayerData"):Clone()
newFolder.Parent = player
--local folder = player:WaitForChild("PlayerData")
local savedValues = DataStore:GetAsync("FolderValues") or "New"
if savedValues == "New" then
print(player.Name.." has started the aventure!")
else
--[[
for _, child in ipairs(folder:GetChildren()) do
for i, childName in ipairs(folderChildren) do
if child.Name == childName then
child.Value = savedValues[i]
print(child.Value)
break
end
end
end
]]
print(savedValues)
for ValName, Val in pairs(savedValues) do
if newFolder:FindFirstChild(ValName) then
newFolder:FindFirstChild(ValName).Value = Val
end
end
end
end)
game.Players.PlayerRemoving:Connect(function(player)
local folder = player.PlayerData
local values = {}
--[[
for _, child in ipairs(folder:GetChildren()) do
for i, childName in ipairs(folderChildren) do
if child.Name == childName then
values[i] = child.Value
print(child.Value)
break
end
end
end
]]
for _, Val in pairs(player:FindFirstChild("PlayerData"):GetChildren()) do -- set it to the folder of values in player
print(Val.Name, Val.Value)
values[Val.Name] = Val.Value
end
warn(values)
DataStore:SetAsync("FolderValues", values)
end)
Edit: Like keep trying over and over, it only sometimes works. Is this some sort of studio bug.
If not, theres a chance that when studio closes, it has not enough time to save the datastore, thats why pcall prints are useful, try this and watch prints:
game.Players.PlayerAdded:Connect(function(player)
local newFolder = script:WaitForChild("PlayerData"):Clone()
newFolder.Parent = player
local savedValues = DataStore:GetAsync("FolderValues") or "New"
if savedValues == "New" then
print(player.Name.." has started the aventure!")
else
print(savedValues)
for ValName, Val in pairs(savedValues) do
if newFolder:FindFirstChild(ValName) then
newFolder:FindFirstChild(ValName).Value = Val
end
end
end
end)
game.Players.PlayerRemoving:Connect(function(player)
local folder = player.PlayerData
local values = {}
for _, Val in pairs(player:FindFirstChild("PlayerData"):GetChildren()) do
--print(Val.Name, Val.Value)
values[Val.Name] = Val.Value
end
warn(values)
local succ, err = pcall(function()
return DataStore:SetAsync("FolderValues", values)
end)
if succ then
warn("Data saved!")
else
warn("failed to save", err)
end
warn("end of script") -- if this doesnt print means that game is closing before saving
end)
game:BindToClose() fires when server is shutting down/closing. It gives you the chance to perform certain tasks as saving player’s datastores before it closes, to make sure the data is really saved and not lost.
Sometimes in studio due to many tasks your game is doing when closing etc, its not really having enough time to save the datastore. The prints/warns will be usefull to let you know if studio actually saved the datastore or not, check the prints at the end of the script I sent.
if succ then
warn("Data saved!")
else
warn("failed to save", err)
end
warn("end of script") -- if this doesnt print or any of previous warns means that game is closing before saving