I’ve started a game, and I need to save a multiplier stat. I’m using datastores, but for some reason it won’t save correctly. pCall is saying that both saving and loading work, so I have no idea what the issue is. I do have another script, which gives you cash and multiplier when you get enough cash and shows those stats on a Gui. I can provide that script if anyone would like to see it. Might anyone have any ideas with what’s wrong?
local DataStoreService = game:GetService("DataStoreService")
local StatStore = DataStoreService:GetDataStore("StatStore")
game.Players.PlayerAdded:Connect(function(player)
local leaderstats = Instance.new("Folder")
leaderstats.Name = "leaderstats"
leaderstats.Parent = player
--Stats
local Multi = Instance.new("IntValue")
Multi.Name = "Multi"
Multi.Parent = leaderstats
local Cash = Instance.new("NumberValue")
Cash.Name = "Cash"
Cash.Parent = leaderstats
--Loading stats
local multidata = 0
local success, errormessage = pcall(function()
multidata = StatStore:GetAsync(tostring(player.UserId).."Multi")
end)
if success then
Multi.Value = multidata
print("Data Succesfully Restored")
else
print("Error in retreiving data.")
warn(errormessage)
end
end)
game.Players.PlayerRemoving:Connect(function(player)
local success, errormessage = pcall(function()
local data = StatStore:SetAsync(tostring(player.UserId).."Multi",player.leaderstats.Multi.Value)
end)
if success then
print("Player Data Saved Succesfully")
else
print("There was an error in saving data...")
warn(errormessage)
end
end)
game:BindToClose(function()
for i,v in pairs(game.Players:GetPlayers()) do
v:Kick("Server Shutdown")
wait(0.2)
end
wait(3)
end)
I’ve turned on studio access to API and made sure that everyone’s data is saved when the server shuts down. I’m completely stuck.
Yeah that is true. Also maybe try updateasync. It is much more reliable than setasync since it will keep running until it runs out of retrys or until its finished. You can also use it to compare data since the callback function passed to updateasync returns the old value too.
.PlayerRemoving won’t fire in studio if the locally hosted server closes before the player instance is removed hence if you’re testing in studio it’s best to use :BindToClose().
I tried changing the script, to use UpdateAsync, but it didn’t work. Am I still doing something wrong? I’m somewhat new to scripting, especially datastores, so that could be the case.
local success, errormessage = pcall(function()
StatStore:UpdateAsync(tostring(player.UserId).."Multi", function(old)
return player.leaderstats.Multi.Value
end)
end)
if success then
print("Player Data Saved Succesfully")
else
print("There was an error in saving data...")
warn(errormessage)
end
end)
This works for me, Let me know if this fixes any of the issues you are facing.
-- Variables --
local DataStoreService=Game:service'DataStoreService';
local StatsDataStore=DataStoreService:GetDataStore'Player_Stats';
-- Load data. --
LoadData=function(Player)
-- Check if already loaded data for player. --
if(Player:GetAttribute'DataLoaded')then
-- We did so return. --
return;
end;
-- Set DataLoaded. --
Player:GetAttribute'DataLoaded'
-- Create leaderstats. --
local a=Instance.new'Folder';
a.Name='leaderstats';
a.Parent=Player;
-- Create stats --
local b=Instance.new'IntValue';
b.Name='Multi';
b.Parent=a;
local c=Instance.new'NumberValue';
c.Name='Cash';
c.Parent=a;
-- Loop through all stats in leaderstats. --
for _,d in next,a:children() do
-- Spawn it to it doesn't yeild. --
Spawn(function()
-- Load data from datastore. --
local Success,Error=ypcall(function()
d.Value=(StatsDataStore:GetAsync(('%s_%s'):format(Player.UserId,d.Name)))or(0);
end);
-- Check for any errors. --
if(not(Success))then
-- Warn. --
warn(Error);
end;
end);
end;
end;
-- Load data to datastores. --
local SaveData=function(Player)
-- Clone stats. --
local Stats=Player.leaderstats:clone();
-- Loop through all stats in leaderstats. --
for _,d in next,Stats:children() do
-- Spawn it to it doesn't yeild. --
Spawn(function()
-- Save data to datastore. --
local Success,Error=ypcall(function()
-- UpdateAsync is better than SetAsync. --
StatsDataStore:UpdateAsync(('%s_%s'):format(Player.UserId,d.Name),function(Old)
-- Return their new stats or their old ones. --
return(d.Value)or(Old);
end);
end);
-- Check for any errors. --
if(not(Success))then
-- Warn. --
warn(Error);
end;
end);
end;
end;
-- New player --
Game.Players.PlayerAdded:connect(LoadData);
-- Player leaving. --
Game.Players.PlayerRemoving:connect(SaveData);
-- Early joiners, if any. --
for _,a in next,Game.Players:players() do
-- Load. --
LoadData(a);
end;
-- Bind to close. --
Game:BindToClose(function()
Wait(3);
end);