Help with DataStore not saving/working (PlayerRemoving/game:BindToClose)

Hello!

(PLEASE READ THE COMMENTS TO SEE WHERE I AM AT)

While developping my game, I wanted to learn how to use DataStores, everything works fine, exept one thing. One very annoying thing:

The annoying thing

data doesn’t always save

Yep, Data doesn’t always save. Which is actually annoying. Worse even is when it works then later it won’t and rarily save.
(Please keep in mind:
I started with one DataValue just to get the basics and I’m gonna add more.
I’ll share the scripts with the only data to see if there’s any small but consequential.
it doesn’t say any errors it would normally say)

So I’ll share my scripts here:

Base Data script

Script Type: Normal Script
Parent: ServerScriptService
Notes: I will add more Data, I just started with one to get the basics.
Code:

local DataStoreService = game:GetService("DataStoreService")
local DataStore1 = DataStoreService:GetDataStore("DataStore1")

game.Players.PlayerAdded:Connect(function(player)
	local leaderstats = Instance.new("Folder")
	leaderstats.Name = "leaderstats"
	leaderstats.Parent = player

	local Name = Instance.new("StringValue")
	Name.Name = "NickName"
	Name.Parent = leaderstats

	local PlayerUserid = "Player_"..player.UserId

	local Data

	
	local success, errormessage = pcall(function()
		Data = DataStore1:GetAsync(PlayerUserid)
	end)
	if success then
		if Data ~= nil then
			Name.Value = Data
		else
			Name.Value = player.Name
		end
	else
		print(errormessage)
	end
end)

game.Players.PlayerRemoving:Connect(function(player)
	local PlayerUserid = "Player_"..player.UserId
	local Data = player.leaderstats.NickName.Value
	
	local success, errormessage = pcall(function()
		DataStore1:SetAsync(PlayerUserid, Data)
	end)
	if success then
		print("Data was saved")
	else 
		print("There was an error")
		warn(errormessage)
	end
end)
Second Script

Script Type: local
Parent(s): TextBox, Frame, Frame, Starter/PlayerGui
Notes: This is based on Nicknames, so this is why I used a TextBox. But please know that the important part is wether I’m doing good.

Code:

    local TextBox = script.Parent 

    local Event = game.ReplicatedStorage.DumbInfo.NickName
    --It's a folder, and a RemoteEvent

TextBox.InputEnded:Connect(function()

local Text = tostring(TextBox.Text)

Event:FireServer(Text)

end)
Third Script

Script Type: Normal
Parent: ServerScriptService
Notes: This is for receiving the event and changing the Value of the Data mentionned.

Code:

local DataStoreService = game:GetService("DataStoreService")
local DataStore1 = DataStoreService:GetDataStore("DataStore1")

local Event = game.ReplicatedStorage.DumbInfo.NickName -- Put RemoteEvent here

Event.OnServerEvent:Connect(function(Player, Text)

local NickName = Player.leaderstats.NickName
NickName.Value = Text

local success, newName = pcall(function()
	return DataStore1:UpdateAsync("Player_1234", Text)
end)

if success then
	print("New NickName:", NickName.Value)
end
	
print("New NickName: "..NickName.Value)
	
end)
Fourth Script

Script Type: Normal
Parent: ServerScriptService
Notes: Basically, it’s used to check whether you change the value already and save it in the TextBox.

Code:

game.Players.PlayerAdded:Connect(function(player)
	local GUI = player.PlayerGui:WaitForChild("PlayersCard").Frame.NNFrame
	local TextLabel = GUI.Default
	local TextBox = GUI.ChangeNickName
	print("PLAYER JOINED")
	print(player.Name.." is crazy") -- I used it to check if we have the correct player, I do dumb stuff in my Outputs.
	local leaderstats = player:WaitForChild("leaderstats")
	local NickName = leaderstats.NickName

print(NickName.Value)
if NickName.Value == "" or nil then
	print("There is no text")
	TextLabel.Visible = false
else
	print("There is text")
	TextLabel.Visible = true
	TextLabel.Text = NickName.Value
		TextBox.Text = NickName.Value
	end
end)

So basically…

Sometimes Data is saved (rarily), sometimes data is wiped (often) and sometimes data isn’t saved at all (often). Data being wiped or not saved are the most often things to occur.

This was a bit long but thanks to those who helped. I’ve been trying to fix this for hours with no good results.

Thanks for reading.

1 Like

You should send the datastore script, not the script you are calling your datastore from.

2 Likes

Ohh, so I should put it all in one script, I’ll try that.

I took a break of developing since it’s the weekend, I’ll comeback ASAP so I don’t make you wait much.

You must use game:BindToClose to save them as sometimes the server closes before they are saved.

Look at this:

By the way, create a debounce or something like that so that they are not saved twice.

2 Likes

I’ll try something, share the script(s) and then say the results.

I’ll try something like this (it will be in the main script):

game:BindToClose(function()

local player = game.Player.LocalPlayer
	local PlayerUserid = "Player_"..player.UserId
	local Data = player.leaderstats.NickName.Value

local success, errormessage = pcall(function()
	DataStore1:SetAsync(PlayerUserid, Data)
end)

if success then
	print("Data was saved")
else 
	print("There was an error")
		warn(errormessage)
	end
end)

So what I’ve gathered is this:

Add game:BindToClose function. In my previous comment I did a small script of what I think it should be, please correct it if it’s wrong.

Also please tell me if it what I’m doing will be easy for me to later on add more Data. As you know as previously mentioned I plan to add more data and since this is my first time using this service I thought it would be good to start with just one data value.

did u actually play like a normal person to test in cause in roblox it doesn’t work often even if u use test service with a server and client it still doesn’t work ?

make sure u test in actualy play and be carfull of what version ur on somtimes it takes up to 5 min for roblox to push the update trough i had that problem when i realized there was nothing wrong just roblox

i also added a while loop on mine and made sure it spawned so other players arent waiting for the old fail to save
and then keep trying until its works
gimme a sec searching for my snippet on my game

Actually I did wait. I tested in both Studio and play testing. So if you know as of right now I need to know how to save on game:BindToClose too since it’s a single player game.

So maybe the server closes and doesn’t to PlayerRemoved function. I will keep that but I should add game:BindToClose.

i believe if u bindclose u say to the server to wait until the script is done but be warned after 30 seconds it wil force shutdown even if script still busy

		print("starting attempt to upload for player:",playerID,"inside Key:",KeyName,"with data:",Data)
		count = 0
		succ,resp = nil,nil
		while not succ do
			if count >= 1 then
				warn(playerID,"Retrying upload, count:", count, "\nError:", resp)
				wait(7)
			end
			--visitsDataStore:SetAsync(playerKey, 0)
			succ, resp = pcall(function() var.CurrentDataStore(playerID):SetAsync(KeyName,Data) end)
			

			count = count + 1
		end
		print("upload SUCCESSFULL for player:",playerID,"Key:",KeyName,"data:",Data)
	end
	-- database > userid|DataStorePrefix > [Backpack] | [Levels]
	spawn(function() upload("Backpack",player.UserId,ToSavePlayerData['Backpack']) end)
	spawn(function() upload("Levels",player.UserId,ToSavePlayerData['Levels']) end)

bindclose im pretty shure there is already a topic of that one solved cause i found it a month ago since i still needed it to add incase i force shutdown a server

1 Like

I’ll try this and what I wrote before. I’ll try both and comeback with results.

Ok so I did something and it seems to work for now:

local Players = game:GetService("Players")

local RunService = game:GetService("RunService")




game:BindToClose(function()

-- if the current session is studio, do nothing
if RunService:IsStudio() then
	print("YOUR IN STUDIO")
	return
end

print("saving player data")

-- go through all players, saving their data
local players = Players:GetPlayers()
for _, player in pairs(players) do
	local playerData = {
		NickName = player.leaderstats.NickName.Value
		
	}

	local userId = player.UserId
	local data = playerData[userId]
	if data then
		-- wrap in pcall to handle any errors
		local success, result = pcall(function()
			-- SetAsync yields so will stall shutdown
			DataStore1:SetAsync(userId, data)
		end)
		if not success then
			warn(result)
		end    
	end
end

	print("completed saving player data")

end)

I’ll comeback if there’s any errors.

Bad news…
Works in studio but not while playing.

This is really tireing. Please anyone seeing this please read the whole thread and help.

I am thinking of making another post. Since it’s inactive.

@foundanerror @GreenMaskEnergy47 @SOTR654
Please help as the problem still isn’t fixed.
(read the whole thread to know where I am at)