Datastore not working without this code

My datastore only works in studio when I include

game:BindToClose(function()
    task.wait(3)
end)

otherwise the changes to leaderstats just don’t save if that code isn’t there
It works in game but not in studio without this code
I think it’s because the server is shutting down before the Datastore:SetAsync() is finished
If I delete that code, why is it working in a game but not in studio and will it be reliable in game without it?
I also feel like a 3 second wait just isn’t efficient code? what should I actually wait for?

1 Like

I’m not really sure what you mean here, but you should have save code implemented for BindToClose and PlayerRemoving events. The reason why it’s likely not working in studio, is because when you stop the studio, it ends the server, hence firing the BindToClose (which fires when the game server ends). I’m not sure why a wait(3) does anything, as it really shouldn’t…

It should be perfectly reliable in game if you have save code implemented hooked to BindToClose AND PlayerRemoving.

when you enter the game in studio the games server runs on your own pc and closing it is instant so without the code it will not save the data, while normal roblox servers take some time to fully close so it has time to save

so does the game.Players.PlayerRemoving not fire when the game closes?
I thought when the game closes it kicks out all the players and then shutsdown the server so the playerremoving would fire for all players

That’s a really good question. I don’t think so, no. Imagine the lifecycle of a server.

Close Server (Stop all scripts from running essentially) → fire game:BindToClose (and finish any operations there) → Disconnect all players.

That means it’s stopping all the scripts thats running. That’s why you should use a for loop to loop through Players:GetPlayers() and run save code for everyone.

That’s weird because it works without any save code for game:BindToClose in game
it only doesn’t work in studio. So it seems in game the PlayerRemoving must be firing otherwise data wouldn’t get saved

It’s suggested to have BindToClose that saves data for any player leaving when the game is about to close and PlayerRemoving when any player in the game leaves without the game closing. BindToClose basically helps save the data in case PlayerRemoving is not firing when the game closes.

to address looping through all players and saving their data on game:BindtoClose
the problem is I tried that a while ago and I got a warning saying something along the lines of “To many data store edit requests” because I was caling setasync on every single person who was in the server.
So I’m asking for too many datastore edit requests
I’ll try again though I might have done something wrong

Not really, I think you misunderstand. Like @CZXPEK said. In studio you host your own server. When you press stop, you are stopping the server, which is why your data doesn’t save, because you’re not saving data in game:BindToClose.

Whereas in game, you’re not stopping the server, you’re just leaving. If you shutdown the server, your data probably wouldn’t save. (Hence why implementing it is very good practice, as you don’t want data loss)

1 Like

I might be wrong that playerRemoving doesn’t fire on server close, but let me check.

Look at the documentation here: DataModel | Documentation - Roblox Creator Hub

You were right, I tried shutting down the server instead of just leaving and not all of my data saved properly. I have two SetAsync()s and only one of them fired
In game

Okay I was wrong, I know why your code works with the wait.

Multiple functions can be bound using BindToClose if it is called repeatedly. The game will wait a maximum of 30 seconds for all bound functions to complete running before shutting down. After 30 seconds, the game will shut down regardless if all bound functions have completed or not.

So, your server was shutting down before setasync operations were completed, whereas with the 3 second wait, your player leaving WAS firing, and it had time to finish operations. Which is why your 3 second wait actually worked. Just implement save code though. It’s good practice!!!

1 Like

So you’re saying

game:BindToClose(function()
    for _, plr in Players:GetPlayers() do
         local Data = nil -- get the player data
         DataStore:SetAsync(tostring(plr.UserId), Data)
    end
end)```
1 Like

You don’t need tostring, but yes, that would be fine.

If you’re already using tostring, do that as numbers and strings are seperate datatypes, so the save files would be different.

isn’t it good practise to ensure it’s the correct data type since Datastore keys will be converted to a string anywway

I don’t think I’ve ever heard that, but even if it does, you don’t need to do that operation for DataStore anyway. Interesting info though.

wait since set async takes time/ yields would it be better if I did

    for _, plr in Players:GetPlayers() do
        task.spawn(function()
               local Data = nil -- get the player data
               DataStore:SetAsync(tostring(plr.UserId), Data)
        end)
    end
end)

this way all the data saving for all players woulud happen simulatneously and make the server wait less time

it won’t let me reply that is odd.

I Solved it here:

what’s wrong with my one

game:BindToClose(function()
    for _, plr in G.Plrs:GetPlayers() do
		OnPlayerRemoving(plr)
	end
end)

On player removing is the same function that fires when a plalyer leavse the game