So you cannot set E_Trail3’s Value to ds:GetAsync(plr.UserId). The data saved is a table. If you want to include this, you need to pack it on removal. Try adding a print in the player added for loop and tell me the result.
Also, are you running any code before playeradded that could yeild the script? This can cause playeradded to not fire in time for the first players to a server (you in studio)
This could be an issue with key length and saving dictionaries in a DataStore. You can try saving to a 2D array instead.
Saving Data:
local data = {}
for i, v in pairs(plr.Inventory.Trails:GetChildren()) do
table.Insert(data, {v.Name, v.Value}
end
ds:SetAsync(plr.UserId, data)
Loading Data:
local function search(data, key)
for _, v in ipairs(data) do
if (v[1] == key) then
return v[2]
end
end
return nil
end
local data = ds:GetAsync(plr.UserId)
for i, v in pairs(plr.Inventory.Trails:GetChildren()) do
local findValue = search(data, v.Name)
if find then v.Value = findValue else print("didn't find") end
end
While this would work, its unpredictable and I wouldn’t do it this way. The order of items in a folder can be unpredictable, especially if new trails are added… The solution I provided allows you to verify by key (trail name).
This is either due to two reasons: the game is not able to save the player’s data in time or the data is too much.
In the case of the situation relating to the first reason. Consider pausing the game’s closure and allowing the player’s data to be saved. You can do this using:
game:BindToClose(function()
wait(5)
end)
Alternatively, you can use coroutine.wrap() for data saving.
If your data happens to not save due to your data consisting of instances. You can serialize your data by turning instances into strings and using those strings to retrieve the given trails or items.
The reason why your script doesn’t work is because a lot of requests sent for SetAsync which can lead to a data reset.
Here is what you should do:
game.Players.PlayerRemoving:Connect(function(plr)
local trail
for i, v in pairs(plr.Inventory.Trails:GetChildren()) do
trail[v.Name] = v.Value
end
if trail then
ds:SetAsync(plr.UserId, trail)
end
end)
But that’s not it, because its only saving 1 trail. So in order to save all of them, we have to make a table for it that stores all of the trails.
Another thing to mention is that you need to use pcalls to detect whether the data saved or not.
This is how you use pcall:
local noerror,error = pcall(function()
game.Woerkspace.Gravity = 100
end)
if noerror then
print("Function is fully working!")
else
print("Function got an error!\nError: "..error)
end
So this is what your script should look like:
game.Players.PlayerRemoving:Connect(function(plr)
local trail = {}
local success,errormsg = pcall()
for i, v in pairs(plr.Inventory.Trails:GetChildren()) do
trail[v.Name] = v.Value
end
end)
if trail and success then
ds:SetAsync(plr.UserId, trail)
else
print("Data has not saved!\nError: "..errormsg)
end
end)
local dataToSave = 10
ds:UpdateAsync(plr.UserId,function(OldData)
return 10
end))
Now this is what your script should look like now:
game.Players.PlayerRemoving:Connect(function(plr)
local trail = {}
local success,errormsg = pcall()
for i, v in pairs(plr.Inventory.Trails:GetChildren()) do
trail[v.Name] = v.Value
end
end)
if trail and success then
ds:UpdateAsync(plr.UserId, function(OldData)
return trail
end))
else
print("Data has not saved!\nError: "..errormsg)
end
end)
Are you setting this through studio’s explore tab? If so, these changes are local to you and are not edited on the server. You need to do it through the command line.