Data value not going up

I am trying to make three data values: deaths, seconds and stages. The deaths should go up once every time the player dies but it goes up like 200 times every time I die once. The seconds should go up by one per second but do not even go up even though I have a while true do loop for it. The stages should go up by once for every checkpoint they touch it (this works). I want all to be saveable when the player leaves the game.

code:

local dss = game:GetService("DataStoreService")
local Datastore = dss:GetDataStore("ObbyData")
local checkpoints = workspace.Checkpoints
					
	local Players = game:GetService("Players")

game:BindToClose(function()
    for _, Player in pairs(Players:GetPlayers()) do
        Player:Kick("This server is shutting down")
    end
    wait(3)
end)local Players = game:GetService("Players")

print("Checkpoints leaderstats working")
print("Deaths leaderstats working")
print("Time leaderstats working")
game.Players.PlayerAdded:Connect(
    function(plr)
        local obbyData = Datastore:GetAsync(plr.UserId .. "-obbyStageProgress")
        local stats = Instance.new("Folder")
        stats.Name = "leaderstats"
        stats.Parent = plr
        local stage = Instance.new("StringValue")
        stage.Name = "Stage"
        stage.Value = (obbyData and obbyData[1]) or 1
        stage.Parent = stats
        local wipeouts = Instance.new("IntValue")
        wipeouts.Name = "Deaths"
        wipeouts.Value =  0
        wipeouts.Parent = stats

        local second = Instance.new("IntValue")
        second.Name = "Seconds"
	        second.Value = 0
	second.Parent = stats
       
        local char = plr.Character or plr.CharacterAdded:Wait()
        char:WaitForChild("HumanoidRootPart").CFrame = checkpoints[stage.Value].CFrame
        char.Humanoid.Touched:Connect(
            function(touch)
                if touch.Parent == checkpoints then
                    if (tonumber(touch.Name) and tonumber(touch.Name) > tonumber(stage.Value)) or touch.Name == "End" then
                        stage.Value = touch.Name
                        pcall(
                            function()
                                Datastore:SetAsync(
                                    plr.UserId .. "-obbyStageProgress",
                                    {plr.leaderstats.Stage.Value, plr.Deaths.Value, plr.Seconds.Value}
                                )
                            end
                        )
                    end
                end

                game.Players.PlayerRemoving:Connect(
                    function(player)
                        Datastore:SetAsync(player.UserId, {player.leaderstats.Stage.Value, player.Deaths.Value}) -- Change "Money" with your currency.
                    end
                )
                plr.CharacterAdded:Connect(
                    function(char)
                        local hrp = char:WaitForChild("HumanoidRootPart")
                        local humanoid = char:WaitForChild("Humanoid")
                        hrp:GetPropertyChangedSignal("CFrame"):Wait()
                        hrp.CFrame = checkpoints[stage.Value].CFrame
			humanoid.Died:Connect(function()
			wipeouts.Value = wipeouts.Value + 1	
			end)
		
                        humanoid.Touched:Connect(
                            function(touch)
				                                
				
                                if touch.Parent == checkpoints then
                                    if
                                        (tonumber(touch.Name) and tonumber(touch.Name) > tonumber(stage.Value)) or
                                            touch.Name == "End"
                                     then
                                        stage.Value = touch.Name
                                        while true do
                                            wait(2)
                                            second.Value = second.Value + 1
                                        end
                                        pcall(
                                            function()
                                                game.Players.PlayerRemoving:Connect(
                                                    function(player)
                                                        Datastore:SetAsync(
                                                            plr.UserId .. "-obbyStageProgress",
                                                            {
                                                                player.leaderstats.Stage.Value,
                                                                player.Deaths.Value,
                                                                player.Seconds.Value
                                                            }
                                                        )
                                                    end
                                                )
                                            end
                                        )
                                    end
                                end
                            end
                        )
                    end
                )
            end
        )
    end
)
			```

Hello!

First of all, I’d suggest you learning how to indent code properly. This is unreadable structure and it is hard helping you when I almost can’t read the code.

You should look into Debounces, though.

I used https://goonlinetools.com/lua-beautifier/ for the indenting

wowwwwwwwwwwwwwwwww

Okay this is whats happening:

  • When a player is created, you make an event with the humanoidrootpart to listen for touches. Since this is only connected once, every time after the character dies and gets a new humanoid root part, this will not fire.
    • But every time this event does fire, it is going to create another connection game.Players.PlayerRemoving. So say you have 5 players, each has fired 50 touch connections, you’ll have 250 event listeners trying to save the player’s data when any player leaves the game.
    • You’re also going to connect a characterAdded event every time the humanoidRootPart touches any object.
      • In here you connect a humanoid death listener. Again if the player touches something 100 times, this event will fire 100 times.
      • And somehow you connect the humanoidrootpart again to a touch listener in this event. Every time this get fires and is a checkpoint, you create the while true loop for seconds.

So your problem is in your control flow and where you’re connecting listeners. Here’s a cleaned up version of the code. I cannot help beyond this.

Yeah
local checkpoints = workspace.Checkpoints

local Players = game:GetService("Players")

game:BindToClose(function()
	for _, Player in pairs(Players:GetPlayers()) do
		Player:Kick("This server is shutting down")
	end
	wait(3)
end)

local Players = game:GetService("Players")

print("Checkpoints leaderstats working")
print("Deaths leaderstats working")
print("Time leaderstats working")

game.Players.PlayerAdded:Connect(function(plr)
	local obbyData = Datastore:GetAsync(plr.UserId .. "-obbyStageProgress")
	local stats = Instance.new("Folder")
	stats.Name = "leaderstats"
	stats.Parent = plr
	
	local stage = Instance.new("StringValue")
	stage.Name = "Stage"
	stage.Value = (obbyData and obbyData[1]) or 1
	stage.Parent = stats
	
	local wipeouts = Instance.new("IntValue")
	wipeouts.Name = "Deaths"
	wipeouts.Value =  0
	wipeouts.Parent = stats

	local second = Instance.new("IntValue")
	second.Name = "Seconds"
	second.Value = 0
	second.Parent = stats

	local char = plr.Character or plr.CharacterAdded:Wait()
	char:WaitForChild("HumanoidRootPart").CFrame = checkpoints[stage.Value].CFrame
	
	
	
	char.Humanoid.Touched:Connect(function(touch)
		if touch.Parent == checkpoints then
			if (tonumber(touch.Name) and tonumber(touch.Name) > tonumber(stage.Value)) or touch.Name == "End" then
				stage.Value = touch.Name
				pcall(function()
					Datastore:SetAsync(plr.UserId .. "-obbyStageProgress", {plr.leaderstats.Stage.Value, plr.Deaths.Value, plr.Seconds.Value})
				end)
			end
		end

		game.Players.PlayerRemoving:Connect(function(player)
			Datastore:SetAsync(player.UserId, {player.leaderstats.Stage.Value, player.Deaths.Value}) -- Change "Money" with your currency.
		end)
	
		plr.CharacterAdded:Connect(function(char)
			local hrp = char:WaitForChild("HumanoidRootPart")
			local humanoid = char:WaitForChild("Humanoid")
			hrp:GetPropertyChangedSignal("CFrame"):Wait()
			hrp.CFrame = checkpoints[stage.Value].CFrame
			humanoid.Died:Connect(function()
				wipeouts.Value = wipeouts.Value + 1	
			end)
	
			humanoid.Touched:Connect(function(touch)
				if touch.Parent == checkpoints then
					if (tonumber(touch.Name) and tonumber(touch.Name) > tonumber(stage.Value)) or touch.Name == "End" then
						stage.Value = touch.Name
						while true do
							wait(2)
							second.Value = second.Value + 1
						end
						pcall(function()
	    					game.Players.PlayerRemoving:Connect(function(player)
	            				Datastore:SetAsync(plr.UserId .. "-obbyStageProgress",
								{
				                    player.leaderstats.Stage.Value,
				                    player.Deaths.Value,
				                    player.Seconds.Value
				                })
	            				
	        				end)
						end)
					end
				end
			end)
		end)
	end)
end)
3 Likes

This isnt really any help but i would recommend learning more about DS2, when i was new to DS and looking for a way to save data it helped me out a lot, You can get more information about it from here How to use DataStore2 - Data Store caching and data loss prevention

in my opinion its much easier to use and since datastore gets leaked and data gets lost every now and then, this is a much more efficient way to save data as its much safer

2 Likes