Hello! I’ve been trying to set up a data store recently for one of my games. However, it’s not working right and I have no idea why.
I run the game and then change one of the values. Then I stop the game. When I run it again, I get that the data was saved as 0, 0 which is not what I set the values.
Here’s my script:
local datastore = game:GetService("DataStoreService"):GetDataStore("Values")
function SaveData(Plr: Player) : ()
local id = Plr.UserId
local cwinsdata = Plr:WaitForChild("leaderstats"):WaitForChild("Casual Wins").Value
local rwinsdata = Plr:WaitForChild("leaderstats"):WaitForChild("Ranked Wins").Value
datastore:SetAsync(id, {cwinsdata, rwinsdata})
end
function GetData(Plr: Player) : ()
local id = Plr.UserId
local gotdata = false
while not gotdata do
local success, errormessage = pcall(function()
return datastore:GetAsync(id)
end)
if success then
gotdata = true
return errormessage
end
wait(0.1)
end
end
local function PlrJoined(Plr: Player): ()
print("doing")
local leaderstats = Instance.new("Folder")
leaderstats.Name = "leaderstats"
leaderstats.Parent = Plr
local cwins = Instance.new("IntValue")
cwins.Name = "Casual Wins"
cwins.Parent = leaderstats
local rwins = Instance.new("IntValue")
rwins.Name = "Ranked Wins"
rwins.Parent = leaderstats
local data = GetData(Plr)
print(data)
if data == nil then
cwins = 0
rwins = 0
else
cwins = data[1]
rwins = data[2]
end
end
game.Players.PlayerAdded:Connect(function(player: Player)
PlrJoined(player)
end)
game.Players.PlayerRemoving:Connect(function(player: Player)
SaveData(player)
end)
game:BindToClose(function()
for i, v in pairs(game.Players:GetChildren()) do
coroutine.wrap(function()
local id = v.UserId
local cwinsdata = v:WaitForChild("leaderstats"):WaitForChild("Casual Wins").Value
local rwinsdata = v:WaitForChild("leaderstats"):WaitForChild("Ranked Wins").Value
datastore:SetAsync(id, {cwinsdata, rwinsdata})
end)
end
end)
Thanks!
1 Like
coroutine.wrap(function()
local id = v.UserId
local cwinsdata = v:WaitForChild("leaderstats"):WaitForChild("Casual Wins").Value
local rwinsdata = v:WaitForChild("leaderstats"):WaitForChild("Ranked Wins").Value
datastore:SetAsync(id, {cwinsdata, rwinsdata})
end)
After coroutine.wrap(function() end) you add an () so it would be
coroutine.wrap(function()
local id = v.UserId
local cwinsdata = v:WaitForChild("leaderstats"):WaitForChild("Casual Wins").Value
local rwinsdata = v:WaitForChild("leaderstats"):WaitForChild("Ranked Wins").Value
datastore:SetAsync(id, {cwinsdata, rwinsdata})
end)()
It wont execute if you dont add an ()
1 Like
Thanks for getting back to me! I’ll try that.
in addition to this, you forgot to set the value of “cwins” and “rwins”!
if data == nil then
cwins.Value = 0
rwins.Value = 0
else
cwins.Value = data[1]
rwins.Value = data[2]
end
2 Likes
Alright thanks!
Also, as an update, I tested it and its now running. However, when the bindtoclose runs, it runs after the player left the game. This is an issue because in my code, I run through the remaining players and save their data.
I added a print(#game.Players:GetChildren()) and got 0.
How do I fix this?
you’re already saving player’s data once they leave, can i ask why you’re using bindtoclose?
If I don’t use a bindtoclose, the server will shutdown before the function for playerremoving will run.
This is wrong; game.Players.PlayerRemoving
runs before the server shutdowns.
If your game has big servers; game:BindToClose(function()
can actually cause more destruction than expected because you’re spamming Datastore:SetAsync
, let alone the risks!
Your best approach would be avoiding this, and giving players an option to save it regularly.
1 Like
I have always been told to use BindToClose in addition to PlayerRemoving. PlayerRemoving never worked for me when i shut down servers or ended games in studio testing. I suppose I could see a problem if it double saves but in my experience it never reaches the PlayerRemoving function
1 Like
BindToClose
is meant for studio testing and stats that aren’t priority, not for data-saving.
Ok but how do I make sure the player’s data saves when they leave? If there really Isn’t a solution, then I guess I’ll have to do a manual save like how @iitreyonly said.
can you explain why it’s not working? does it print any errors?
Ok so there are no errors, the only problem is that the function in PlayerRemoving doesn’t fully run before the server shuts down. Most people suggest that you use BindToClose to fix this issue. However, I implemented that and It’s still not working.
With the BindToClose, it runs the code but it does so after the player already left. This is an issue because in a BindToClose, you need to loop through all the players and save their data. I added a line to the BindToClose at the front.
print(#game.Players:GetChildren))
This in theory would print the number of players left in the game when the code ran. I ran this and got 0.
This is the issue I’m trying to solve.
Thanks for your time!
are you using admin commands to shutdown the server?
No, this is when I leave naturally and I’m the only person in the server.