I'm trying to make a Obby game and I wanted to have both collecting and Stage savings to be both working properly, because I want to make the obby unlike any other obby games that was done before. Here are to codes I typed down;

AutoSave:

--LeaderBoard Script:

game.Players.PlayerAdded:connect(function(p)
	local stats = Instance.new("IntValue")
	stats.Name = "leaderstats"
	stats.Parent = p
		
	local studs = Instance.new("IntValue")
	studs.Name = "Studs"
	studs.Value = 0
	studs.Parent = stats
	
	local minikits = Instance.new("IntValue")
	minikits.Name = "MiniKits"
	minikits.Value = 0
	minikits.Parent = stats

	local redbricks = Instance.new("IntValue")
	redbricks.Name = "RedBricks"
	redbricks.Value = 0
	redbricks.Parent = stats

	local goldbricks = Instance.new("IntValue")
	goldbricks.Name = "GoldBricks"
	goldbricks.Value = 0
	goldbricks.Parent = stats

	local kyberbricks = Instance.new("IntValue")
	kyberbricks.Name = "KyberBricks"
	kyberbricks.Value = 0
	kyberbricks.Parent = stats

	local mithrilbricks = Instance.new("IntValue")
	mithrilbricks.Name = "MithrilBricks"
	mithrilbricks.Value = 0
	mithrilbricks.Parent = stats
end)


--Datastore Script:

local AUTO_SAVE = true			-- Make true to enable auto saving
local TIME_BETWEEN_SAVES = 60	-- In seconds (WARNING): Do not put this lower than 60 seconds
local PRINT_OUTPUT = true		-- Will print saves and loads in the output
local SAFE_SAVE = true			-- Upon server shutdown, holds server open to save all data
---------------------------------

local players = game:GetService("Players")
local dataStoreService = game:GetService("DataStoreService")
local leaderboardData = dataStoreService:GetDataStore("LeaderStats")

local function Print(message)
	if PRINT_OUTPUT then print(message) end
end

local function SaveData(player)
	if player.userId < 0 then return end
	player:WaitForChild("leaderstats")
	wait()
	local leaderstats = {}
	for i, stat in pairs(player.leaderstats:GetChildren()) do
		table.insert(leaderstats, {stat.Name, stat.Value})
	end
	leaderboardData:SetAsync(player.userId, leaderstats)
	Print("Saved "..player.Name.."'s data")
end

local function LoadData(player)
	if player.userId < 0 then return end
	player:WaitForChild("leaderstats")
	wait()
	local leaderboardStats = leaderboardData:GetAsync(player.userId)
	
	for i, stat in pairs(leaderboardStats) do
		local currentStat = player.leaderstats:FindFirstChild(stat[1])
		if not currentStat then return end
		currentStat.Value = stat[2]
	end
	Print("Loaded "..player.Name.."'s data")
end

players.PlayerAdded:connect(LoadData)
players.PlayerRemoving:connect(SaveData)

if SAFE_SAVE then
	game.OnClose = function()
		for i, player in pairs(players:GetChildren()) do
			SaveData(player)
		end
		wait(1)
	end
end

while AUTO_SAVE do
	wait(TIME_BETWEEN_SAVES)
	for i, player in pairs(players:GetChildren()) do
		SaveData(player)
	end
end

Here's another code;

Plrhandler:

local player = game:GetService("Players")
local dataStoreService = game:GetService("DataStoreService")
local saveDataStore = dataStoreService:GetDataStore("SaveDataTest")

local function savePlrData(plr)

	local success,err = pcall(function()

		local saveData = {}
		
		for _,stat in pairs(plr.leaderstats:GetChildren())do
	
			saveData[stat.Name] = stat.Value
	
		end

		saveDataStore:SetAsync(plr.UserId,saveData)

	end)

	if not success then return err end

end

player.PlayerAdded:connect(function(plr)

	local stats = Instance.new("Folder")
	stats.Name = "leaderstats"
	stats.Parent = plr

	local stage = Instance.new("IntValue")
	stage.Name = "Stage"
	stage.Parent = stats

	local data = saveDataStore:GetAsync(plr.UserId)

	if data then

		print(data.Stage)
		
		for _,stat in pairs(stats:GetChildren()) do

			stat.Value = data[stat.Name]
		
	end
	
else

		print(plr.Name .. " has no data")

	end

	plr.CharacterAdded:connect(function(char)
	
		local humanoid,hrp = char:WaitForChild("Humanoid"),char:WaitForChild("HumanoidRootPart")

		wait()

		if humanoid and hrp then

			if stage.Value ~= 0 then

				local part = workspace.ObbyStages:FindFirstChild(stage.Value)
				hrp.CFrame = part.CFrame + Vector3.new(0,1,0)

			end

   		end

	end)

end)

player.PlayerRemoving:connect(function(plr)

	local err = savePlrData(plr)

	if err then print(err) end

end)

game:BindToClose(function()

	for _,plr in pairs(player:GetPlayers()) do

		local err = savePlrData(plr)

		if err then print(err) end

	end

	wait(2)

end)

I also will include this code as well, incase if it will help with problem solving.

ObbyHandler:

local obbyStages = workspace:WaitForChild("ObbyStages")

for _,stage in pairs(obbyStages:GetChildren()) do

	stage.Touched:connect(function(hit)

		local hum
		
		if hit.Parent:FindFirstChild("Humanoid") then
		
			hum = hit.Parent.Humanoid

	end

		if hit.Parent and hit.Parent.Parent:FindFirstChild("Humanoid") then

			hum = hit.Parent.Parent.Humanoid

		end

			if hum then

				local plr = game.Players:GetPlayerFromCharacter(hum.Parent)
				
				local plrStage = plr.leaderstats.Stage.Value
			
				if tonumber(stage.Name) == plrStage + 1 then

					plr.leaderstats.Stage.Value = plr.leaderstats.Stage.Value + 1

				elseif tonumber(stage.Name) > plrStage + 1 then

					hum.Health = 0
				
				end
	

		end
	

	end)


end

I hope the problems will get fixed, otherwise, it'll be critical bug among the players if I released the game like this.