It looks like you’re saving data every time the stat changes. Generally speaking, this isn’t an efficient way to go about this. In my own work to save data, I usually save data whenever a player leaves the game with PlayerRemoving, as well as hooking it up to a BindToClose function. It would also be smart to store all values in a table of some sorts and save that, instead of using multiple datastores.
local service = game:GetService("DataStoreService")
local datastore = service:GetDataStore("stat") --Data store name
game.Players.PlayerAdded:Connect(function(plr)
local leaderstats = Instance.new("Folder", plr)
leaderstats.Name = "leaderstats"
local stat = Instance.new("IntValue", leaderstats)
stat.Name = "stat" --Stat name
local data
local success, errorMessage = pcall(function()
data = datastore:GetAsync(plr.UserId.."-stat") --change stat to currency name
end)
if success then
stat.Value = data
else
warn(errorMessage)
end
end)
game.Players.PlayerRemoving:Connect(function(plr)
local success, errorMessage = pcall(function()
--change both stat to stat name
datastore:SetAsync(plr.UserId.."-stat", plr.leaderstats.stat.Value)
end)
if not success then
warn(errorMessage)
end
end)
This looks like you’re using pcalls as well as PlayerRemoving, meaning this would be a good alternative which should prevent the error! If you don’t use it because it’s too complicated, allow me to explain some concepts!
Loading in data here, you’ll notice it’s wrapped in something called a “pcall”. Pcalls are good, as if something fails within the block, it won’t stop the entire rest of the script from running. This is useful for datastores and stuff, as anything contacting something externally from Roblox has the chance to fail every now and then.
local data
local success, errorMessage = pcall(function()
data = datastore:GetAsync(plr.UserId.."-stat") --change stat to currency name
end)
The block below says that if the data was loaded in, set the value to the data. Else, If it’s not successful, then warn the output of the error message.
if success then
stat.Value = data
else
warn(errorMessage)
end
end)
Other than that I think everything else you used in your original script other than PlayerRemoving! It might also be a good idea to add BindToClose in there as well!
No worries. BindToClose is useful if the server shuts down unexpectedly (ie the game crashes or something). Here is a quick sample.
game:BindToClose(function()
for i, plr in pairs(game.Players:GetPlayers()) do
--save the players data here, basically what you did in playerRemoving.
end
end)