Data loss issues with datastores

You’ll benefit from using this instead:

Some quick tips:

1: Don’t use FindFirstChild unless you’re going to guarantee the child exists

The point of FindFirstChild is to ensure that object exists. Here, you use the function but not check if it exists. If it doesn’t exist, it will error. If this is on the client, it should use WaitForChild once, not on every line the object is used.

2: Avoid variable desync possibility in pcall

If the code fails to save your data, the playersleft variable will not change, causing something I like to call variable desync. It’s when your variables do not represent the situation accurately anymore for whatever reason. In this case, it’s because the code might not reach it. Instead, you should put this variable assignment outside the pcall to ensure it will always run. The event should also be fired outside of the pcall.

3: Avoid BindToClose in Studio

This code will be fine assuming the pcall doesn’t fail. If the pcall fails, the event will not fire, causing this to hang studio for 10-30 seconds. BindToClose stops waiting for the function to be finished after the 10-30 seconds. It would be annoying to wait this long! Even if the pcall doesn’t fail, it could still take time to save your data if roblox is down.

4: Pcall shouldn’t set any outside variables

This code will work, but to make it cleaner, you should instead return the new data:

local ran, result = pcall(function()
    return DataStore:GetAsync(PlayerUserId)
end)

print(ran, result) --> boolean?, table|string?

5: Avoid messy variables

Assuming the variable works completely, it is still not required. You should use #game.Players:GetPlayers() unless optimization is a serious concern in your project! If you use this multiple times in one place, consider making a variable to game.Players:GetPlayers() so you can access the players AND the amount of players easily. This table won’t update itself with new players.

1 Like