Save data leaderstats don't working after change stats

(Explanation of the problem)

Hello everyone! I made a script for saving Clicks and Rebirths. But for some reason there was a problem that after exiting the game statistics are not saved, it (statistics) is saved only when the console commands:

game.Players.{Name}.leaderstats.Clicks.Value += {any number}.

I have a button where you need to press to increase the statistics of clicks.

(The main purpose of this issue)

Force save all statistics changes

(Scripts)
Script Button (StarterGui.ScreenGui.ClickButton.LocalScript):

local ClickButton = script.Parent
local player = game.Players.LocalPlayer
local Clicks = player:WaitForChild("leaderstats"):WaitForChild("Clicks")
local Rebirths = player:WaitForChild("leaderstats"):WaitForChild("Rebirths")
local PLUSREBITH = 1

function use()
	Clicks.Value += PLUSREBITH
	if Clicks.Value > 100 then
		Clicks.Value = 0
		Rebirths.Value = Rebirths.Value +1
        PLUSREBITH += 1
	end
end
script.Parent.MouseButton1Click:Connect(use)

Script SaveManager (ServerScriptService.SaveMeneger):

local DataStoreService = game:GetService("DataStoreService")
local dataStore = DataStoreService:GetDataStore("DataStore")

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

	local Rebiths = Instance.new("IntValue")
	Rebiths.Parent = leaderstats
	Rebiths.Name = "Rebirths"
	
	local data, data2
	local success, errormassage = pcall(function()
		data = dataStore:GetAsync(plr.UserId.."-Clicks")
		data2 = dataStore:GetAsync(plr.UserId.."-Rebirths")
	end)
	
	if success then
		Clicks.Value = data
		Rebiths.Value = data2
		print("Load data successfully!")
	else
		Clicks.Value = 0
		Rebiths.Value = 0
		print("Error save data, send it in discord server 'link'")
		warn(errormassage)
	end	
end)

game.Players.PlayerRemoving:Connect(function(plr)
	local succes, errormassage = pcall(function()
		dataStore:SetAsync(plr.UserId.."-Clicks", plr.leaderstats.Clicks.Value)
		dataStore:SetAsync(plr.UserId.."-Rebirths", plr.leaderstats.Rebiths.Value)
	end)
	
	if succes then
		print("Data save successfully!")
	else
		print("There was an issue while saving data")
		warn(errormassage)
	end
	
end)

This is because you are trying to modify the values ​​by local script (Client -Side), the datastore only saves data that is received by the server-side.

Change the values ​​by a script.

Are

You need to fire a remote event here and make these modifications there. Because at the moment these changes are happening to the client.

1 Like

I’m sorry, I’m new to Roblox Studion. Can you explain in more detail how to do it?

You can learn more about Remote Events and Functions here if it helps: Remote Functions and Events

1 Like

What is a LocalScript?

A LocalScript is a type of script which handles modifications and interactions within the client. For example changing the position, size, transparency, color of a GUI etc. There are much more you can do within a LocalScript but this is a summarized explanation.

What is a Script?

A Script is alternatively known as a ServerScript. A Script is a type of script which handles modifications and interactions within the server. For example changing the WalkSpeed of a humanoid, changing player data (taking your one problem as an example), modifications of values etc. There are much more you can do within a Script but this is a summarized explanation.

Now that you have learned about LocalScript and Script, let’s start learning about Remote Events.

What are RemoteEvents?

RemoteEvent(s) are instances which are used to communicate between the client and the server. RemoteEvent(s) are usually placed under ReplicatedStorage or under a folder in ReplicatedStorage (if you have too many RemoteEvent(s) you can use a folder to organize it). Here’s something you need to know. Sending values are optional so if you don’t intend on sending any values just keep it blank.

The functions and events you need to know:

Functions:

FireServer: (…): It is a function through which you can send information from the client to the server. But it must be known that the client information is valid on the server. So, here is an example. You create a part using Instance.new() on the client, send it through the RemoteEvent, but when receiving it, the server will find it as nil since the part isn’t available on the server.
RemoteEvent:FireServer(...)

FireClient: (Player: Player, …): It is a function through which you can send information from the server to the client. Even if you don’t want to send any values to the client, it is a must to put the Player in the first argument since you’re communicating with the client.
RemoteEvent:FireClient(Player: Player, ...)

FireAllClients: (…): Same as FireClient, except you don’t need to put the Player argument and it sends to every client in the server.
RemoteEvent:FireAllClients(...)

Events:

OnServerEvent: When you fire your RemoteEvent from the client to the server, you use the OnServerEvent event to receive it. Here’s an example of how you use it:

RemoteEvent.OnServerEvent:Connect(function(Player: Player, ...)
    -- Code
end)

This event gives you the player who fired the RemoteEvent as the 1st argument and the other ones as the ones you sent through FireServer function if you sent any.

OnClientEvent: Same as OnServerEvent except it is received on the client and it doesn’t provide you with the player as the 1st argument since you can get the player using game.Players.LocalPlayer (You use OnClientEvent when you use FireAllClients as well.)

Now, here is an example:
A client sends a text to the server using a TextButton and a TextBox and the server tries to put your text on a BillboardGui. Without RemoteEvent(s) the action is impossible. So, let’s try doing this example right here!

Inside the LocalScript

--// Services
local ReplicatedStorage = game:GetService("ReplicatedStorage")

--// ReplicatedStorage Variables
local SendTextRE = ReplicatedStorage:WaitForChild("SendTextRE")
-- RE(RemoteEvent)

--// GUI Variables
local TextButton = script.Parent.TextButton
local TextBox = script.Parent.TextBox

--// Main
TextButton.MouseButton1Click:Connect(function()
    if TextBox.Text ~= nil then -- Checking if the text of the TextBox isn't nil
        SendTextRE:FireServer(TextBox.Text)
    end
end)

Inside the Script

--// Services
local ReplicatedStorage = game:GetService("ReplicatedStorage")

--// ReplicatedStorage Variables
local SendTextRE = ReplicatedStorage:WaitForChild("SendTextRE")

--// Main
SendTextRE.OnServerEvent:Connect(function(Player, Text)
    game.Workspace.Part.BillboardGui.TextLabel.Text = Player.Name .. "sent the text: " .. Text
end)

Now, that we have completely learned about RemoteEvents let’s try to fix your problem!

Inside your use function in the LocalScript, you change the Clicks’ and the Rebirths’ value which is supposed to be changed on the server. So, let’s change that!

(Please rename this remote event I can’t find ideas to what I can name this remote event to.)
local ClickButton = script.Parent
local player = game.Players.LocalPlayer
local ChangeLeaderstatsValue = game.ReplicatedStorage:WaitForChild("ChangeLeaderstatsValue")

function use()
	ChangeLeaderstatsValue:FireServer() -- We don't need to send any information because it's useless.
end
script.Parent.MouseButton1Click:Connect(use)

And now in our Script:

local DataStoreService = game:GetService("DataStoreService")
local dataStore = DataStoreService:GetDataStore("DataStore")
local ChangeLeaderstatsValue = game.ReplicatedStorage:WaitForChild("ChangeLeaderstatsValue")
local PLUSREBIRTH = 1

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

	local Rebiths = Instance.new("IntValue")
	Rebiths.Parent = leaderstats
	Rebiths.Name = "Rebirths"
	
	local data, data2
	local success, errormassage = pcall(function()
		data = dataStore:GetAsync(plr.UserId.."-Clicks")
		data2 = dataStore:GetAsync(plr.UserId.."-Rebirths")
	end)
	
	if success then
		Clicks.Value = data
		Rebiths.Value = data2
		print("Load data successfully!")
	else
		Clicks.Value = 0
		Rebiths.Value = 0
		print("Error save data, send it in discord server 'link'")
		warn(errormassage)
	end	
end)

game.Players.PlayerRemoving:Connect(function(plr)
	local succes, errormassage = pcall(function()
		dataStore:SetAsync(plr.UserId.."-Clicks", plr.leaderstats.Clicks.Value)
		dataStore:SetAsync(plr.UserId.."-Rebirths", plr.leaderstats.Rebiths.Value)
	end)
	
	if succes then
		print("Data save successfully!")
	else
		print("There was an issue while saving data")
		warn(errormassage)
	end
	
end)

ChangeLeaderstatsValue.OnServerEvent:Connect(function(Player) -- Receiving the remote event here.

	-- Doing all the modifications in the server instead of in the client
	local Clicks = Player:WaitForChild("leaderstats"):WaitForChild("Clicks")
	local Rebirths = Player:WaitForChild("leaderstats"):WaitForChild("Rebirths")
	Clicks.Value += 1

	if Clicks.Value > 100 then
		Clicks.Value = 0
		Rebirths.Value += 1
		PLUSREBIRTH += 1
	end
end)

Again, yes. As @HMgamingTheSecondary (Apologize for pinging) said, you should check out the page about Remote Functions and Events

1 Like