The 2 values I want to save are player.ForSaving.Avatar.Shirt and then all that but with Pants. In the output it says unable to cast value to function. Btw, I have it so when a player changes their avatar, it also changes the values in the player. Thanks for any help!
Im not the best at scripting as you can probably tell
local DSS = game:GetService("DataStoreService")
local myDS = DSS:GetDataStore("myDataStore")
local PlayersToSave = {}
local TimeBetweenAutoSave = 60
function SavePlayersData(player)
local key = "Player_"..player.UserId
local Shirt = player.ForSaving.Avatar.Shirt.Value
local Pants = player.ForSaving.Avatar.Pants.Value
local success, errormessage = pcall(function()
myDS:UpdateAsync(key, Shirt)
myDS:UpdateAsync(key, Pants)
end)
if success then
player.PlayerGui.MainGui.Saving.Visible = true -- This is just a little gui that tells the player if the save worked
player.PlayerGui.MainGui.Saving.TextLabel.Text = ("Saved")
print("Data save was successfull!")
wait(3)
player.PlayerGui.MainGui.Saving.Visible = false
else
player.PlayerGui.MainGui.Saving.Visible = true
player.PlayerGui.MainGui.Saving.TextLabel.Text = ("Save failed")
print("Data save failed...")
warn(errormessage)
wait(3)
player.PlayerGui.MainGui.Saving.Visible = false
end
end
game.Players.PlayerAdded:Connect(function(player)
-- Make data save folder
local ForSaving = Instance.new("Folder")
ForSaving.Name = "ForSaving"
ForSaving.Parent = player
-- Make avatar save folder
local AvatarFolder = Instance.new("Folder")
AvatarFolder.Name = "Avatar"
AvatarFolder.Parent = player.ForSaving
-- Make shirt
local Shirt = Instance.new("IntValue")
Shirt.Name = "Shirt"
Shirt.Parent = AvatarFolder
-- Make pants
local Pants = Instance.new("IntValue")
Pants.Name = "Pants"
Pants.Parent = AvatarFolder
-- Player
local key = "Player_"..player.UserId
-- Load data
local data
local success, errormessage = pcall(function()
data = myDS:GetAsync(key)
end)
if success then
Shirt.Value = data or 0
Pants.Value = data or 0
print("Loaded data!")
end
Shirt.Changed:Connect(function()
table.insert(PlayersToSave,player)
end)
Pants.Changed:Connect(function()
table.insert(PlayersToSave,player)
end)
end)
-- Save when leaving
game.Players.PlayerRemoving:Connect(function(player)
if table.find(PlayersToSave,player) then
SavePlayersData(player)
table.remove(PlayersToSave,table.find(PlayersToSave,player))
end
end)
-- Auto save
while true do
wait(TimeBetweenAutoSave)
spawn(function()
for _, player in ipairs(PlayersToSave) do
SavePlayersData(player)
table.remove(PlayersToSave,table.find(PlayersToSave,player))
print("Data auto saved!")
end
end)
end
UpdateAsync
expects a function as its 2nd argument where you are expected to return the new value that should be in the key or nil
to cancel the update, you gave it a value, did you mean to use SetAsync
in this case?
1 Like
Ok, It said saved but in the output it also said “DataStore request was added to queue. If request queue fills, further requests will be dropped. Try sending fewer requests.Key = Player_117457868” Should I be worried?
Another thing, this script is made off of an old one that was used to save a coins value which was coins and it seems to be loading the coins value instead of the shirt/pants id?
-- Load data
local data
local success, errormessage = pcall(function()
data = myDS:GetAsync(key)
end)
if success then
Shirt.Value = data or 0
Pants.Value = data or 0
print("Loaded data!")
end
Well looking through how you’re doing it, it could be that you autosave every minute or could be that you use SetAsync twice for the same key, meaning in all cases, you’ll only be saving what Pants
contains, you should be Shirt
and Pants
into a table and save that into the Datastore
--To save
local tbl = {Shirt, Pants}
myDS:SetAsync(key, tbl)
--To receive
Shirt.Value = tbl[1]
Pants.Value = tbl[2]
Also what do you mean by loading the coins value?
1 Like
Oh, I messed that up, basically that script used to be a script for saving the players’ coins value but I removed that whole system and now I’m trying to get it to save avatar item ids and when it loads data its loading the coins I used to have which is 7 coins lol
Where do I put the To Save and To Receive?
To Save is where you want the datastore to save your data, To Receive is where you get your data from the datastore, just replace the saving/getting code with those
1 Like
Well your issue is that you alreayd called .Value
and call it again later, but the tbl
when the player joins is not how you’re meant to do that, tbl
is the like the data
variable, it contains the result of GetAsync
1 Like
The current script. Works almost all the way but data loads 0
local DSS = game:GetService("DataStoreService")
local myDS = DSS:GetDataStore("myDataStore")
local PlayersToSave = {}
local TimeBetweenAutoSave = 10 -- will change back, just for testing
function SavePlayersData(player)
local key = "Player_"..player.UserId
local Shirt = player.ForSaving.Avatar.Shirt.Value
local Pants = player.ForSaving.Avatar.Pants.Value
local success, errormessage = pcall(function()
local tbl = {Shirt, Pants}
myDS:SetAsync(key, tbl)
end)
if success then
player.PlayerGui.MainGui.Saving.Visible = true
player.PlayerGui.MainGui.Saving.TextLabel.Text = ("Saved")
print("Data save was successfull!")
wait(3)
player.PlayerGui.MainGui.Saving.Visible = false
else
player.PlayerGui.MainGui.Saving.Visible = true
player.PlayerGui.MainGui.Saving.TextLabel.Text = ("Save failed")
print("Data save failed...")
warn(errormessage)
wait(3)
player.PlayerGui.MainGui.Saving.Visible = false
end
end
game.Players.PlayerAdded:Connect(function(player)
local key = "Player_"..player.UserId
-- Make data save folder
local ForSaving = Instance.new("Folder")
ForSaving.Name = "ForSaving"
ForSaving.Parent = player
-- Make avatar save folder
local AvatarFolder = Instance.new("Folder")
AvatarFolder.Name = "Avatar"
AvatarFolder.Parent = player.ForSaving
-- Make shirt
local Shirt = Instance.new("IntValue")
Shirt.Name = "Shirt"
Shirt.Parent = AvatarFolder
Shirt.Value = myDS:GetAsync(key, Shirt)
-- Make pants
local Pants = Instance.new("IntValue")
Pants.Name = "Pants"
Pants.Parent = AvatarFolder
Pants.Value = myDS:GetAsync(key, Pants)
-- Add values to table
Shirt.Changed:Connect(function()
table.insert(PlayersToSave,player)
end)
Pants.Changed:Connect(function()
table.insert(PlayersToSave,player)
end)
end)
-- Save when leaving
game.Players.PlayerRemoving:Connect(function(player)
if table.find(PlayersToSave,player) then
SavePlayersData(player)
table.remove(PlayersToSave,table.find(PlayersToSave,player))
end
end)
-- Auto save
while true do
wait(TimeBetweenAutoSave)
spawn(function()
for _, player in ipairs(PlayersToSave) do
SavePlayersData(player)
table.remove(PlayersToSave,table.find(PlayersToSave,player))
print("Data auto saved!")
end
end)
end
I decided to make individual scripts for each value lol. Maybe not the best idea, but for now it works. Here’s the script that saves just one of the values for anyone looking at this in the future. Thanks @EmbatTheHybrid for all the help! 
local DSS = game:GetService("DataStoreService")
local myDS = DSS:GetDataStore("myDataStore")
local PlayersToSave = {} -- setup a table to hold players that the data has changed on
local TimeBetweenAutoSave = 60 -- the time between each autosave check if they are in table above to save
function SavePlayersData(player) -- The save function itself call by remove and by autosave
local key = "Player_"..player.UserId
local data = player:FindFirstChild("Avatar").Shirt.Value
local success, errormessage = pcall(function()
myDS:UpdateAsync(key, data)
end)
if success then
print("Success")
else
print("Error")
warn(errormessage)
end
end
game.Players.PlayerAdded:Connect(function(player)
-- Player
local key = "Player_"..player.UserId
-- Load data
local data -- Makes it work in the WHOLE script
local success, errormessage = pcall(function()
data = myDS:GetAsync(key) -- !!!! if data has never been set this will return successful and data will be nil
end)
local Value = player.Avatar.Shirt
if success then
Value.Value = data or 0 -- !!!! this will set a default to the value incase they don't have any data which would be nil
-- Set value = to the data
print("Loaded!")
end
Value.Changed:Connect(function() -- this catches the change of the value either add or subtracted any change to it will then add them to the autosave table for next loop to save the data
table.insert(PlayersToSave,player) -- add the player to this table because their data has changed
end)
end)
-- Save when leaving
game.Players.PlayerRemoving:Connect(function(player)
if table.find(PlayersToSave,player) then -- if the players data changed they will be in this table so save their data on remove else don't -- you can remove this and just do a save here if you want but may overload datastore
SavePlayersData(player) -- save when they leave if it can sometimes this doesn't save in studio
table.remove(PlayersToSave,table.find(PlayersToSave,player)) -- after save then remove them from the table
end
end)
-- Auto save
while true do -- this autosave loop only saves player data if it has changed
wait(TimeBetweenAutoSave)
spawn(function() -- Spawn incase of error
for _, player in ipairs(PlayersToSave) do -- go through all the players in the PlayersToSave because their data changed and save them
SavePlayersData(player) -- save when they leave if it can sometimes this doesn't save in studio
table.remove(PlayersToSave,table.find(PlayersToSave,player))
-- After save then remove player from table
print("Auto saved!")
end
end)
end