✓ Accepted answer
You are connecting a PlayerAdded event to your function every second. If a player joins after 60 seconds, this means that your function will run 60 times!
Fortunately, we don't need the loop at all -- just listen for the Changed event.
local DataStore = game:GetService("DataStoreService"):GetDataStore("Cash")
game.Players.PlayerAdded:connect(function(player)
local key = "user_" ..player.userid
local v = player:WaitForChild("Value")
v.Value = DataStore:GetAsync(key) or 0
v.Changed:connect(function()
DataStore:UpdateAsync(key, function(oldValue)
if oldValue == v.Value then return end
return v.Value
end)
end)
end)
However, according to the API, datastores may error unexpectedly, which is why I recommend wrapping calls to the datastores in pcall. I've written a small function, "Try10", which will attempt to run a function up to 10 times before giving up. The full script:
local DataStore = game:GetService("DataStoreService"):GetDataStore("Cash")
function Try10(Func)
local success, message
for i = 1, 10 do
success, message = pcall(Func)
if success then return success, message end
wait(0.1)
end
return success, message
end
game.Players.PlayerAdded:connect(function(player)
local key = "user_" ..player.userid
local v = player:WaitForChild("Value")
local success, message = Try10(function()
v.Value = DataStore:GetAsync(key) or 0
end)
if not success then warn("Unable to load cash value from datastores: " .. tostring(message)) end
v.Changed:connect(function()
local success, message = Try10(function()
DataStore:UpdateAsync(key, function(oldValue)
if oldValue == v.Value then return end
return v.Value
end)
end)
if not success then warn("Unable to save cash value to datastores: " .. tostring(message)) end
end)
end)
2 comments
Thank you! I have never had a better and most straightforward answer before.
Ah, yes, I remember when I first discovered the Changed event. It's a really useful one for things like this.