Help with a script (Touched events)

So a bit of back story before I explain the question more:

I am trying to make it so that when a player jumps down and touches an invisible part, their “Time” goes up by 1. I have this part done already. In the first gyazo gif, it shows what I mean.

https://gyazo.com/2b5234be5de2bc4c5d476033f579a4f2

However, the problem lies when they die. Once they die, their time gets reset to 0, making them have to go up again (which is what I intend), but when the player jumps down again, it doesn’t increment by 1. It goes up by a random value + 1. I tried using booleans and many other things, but can’t seem to figure it out. Here is what I mean:

https://gyazo.com/a6d8253afe77809b7e0ac54f9131a18e

If anyone can help, that would be amazing. Here is my script for reference (if you wish to replicate or see what I did):

local region = game.Workspace:WaitForChild("Region")

local canActivate = true
local dead = false
local loop = true

local function addTime()
	while true do
		local players = game.Players:GetPlayers()
			if #players >= 1 and not dead and canActivate and loop then
			for _, player in pairs(players) do
				local leaderstats = player:FindFirstChild("leaderstats")
				if not leaderstats then continue end 
				local time = leaderstats:FindFirstChild("Time")
				local bestTime = leaderstats:FindFirstChild("BestTime")
				if not time or not bestTime then continue end
			
				time.Value = time.Value + 1
				if time.Value > bestTime.Value then
					bestTime.Value = time.Value
					canActivate = false
				end
			end
		end
		wait(1)
		canActivate = true
	end
end

local function initLeaderstats(player)
	local leaderstats = Instance.new("Folder")
	leaderstats.Name = "leaderstats"
	leaderstats.Parent = player
	
	local timeValue = Instance.new("IntValue")
	timeValue.Name = "Time"
	timeValue.Parent = leaderstats
	
	local bestTimeValue = Instance.new("IntValue")
	bestTimeValue.Name = "BestTime"
	bestTimeValue.Parent = leaderstats
		
	return leaderstats, timeValue, bestTimeValue
end

game.Players.PlayerAdded:Connect(function(player)
	local leaderstats, timeValue, bestTimeValue = initLeaderstats(player)
	
	player.CharacterAdded:Connect(function(char)
		local humanoid = char:WaitForChild("Humanoid")
		humanoid.Died:Connect(function()
			timeValue.Value = 0
			dead = false
			loop = false
		end)
	end)
end)

region.Touched:Connect(function(Hit)
	local player = game.Players:GetPlayerFromCharacter(Hit.Parent)
	if player and canActivate then
		dead = false
		loop = true
		addTime(player)
	end
end)

It might be because you didn’t break the loop when the player died.

I tried to do that, however it didn’t work when I did it.

It’s because the addTime function has a non-terminating loop not running in a coroutine. It’s blocking any code from being reached that might run after the addTime function. A quick fix to this is to wrap your function in a coroutine and call it.

coroutine.wrap(addTime)(player)

I haven’t read your entire code in full though and I believe that there might be a better way to do what you’re doing right now. Assuming that this coroutine fix works, you might end up spawning a lot of coroutines for no reason. You might want to handle counting in a different way such that only a single loop is running to update all time, rather than having a loop in a function that’s called every time a part is touched.

local Region = workspace:WaitForChild("Region")
local threads = {}


game.Players.PlayerAdded:Connect(function(player)
	local Leaderstats = Instance.new("Folder", player)
	Leaderstats.Name = "leaderstats"
	local Time = Instance.new("IntValue", Leaderstats)
	Time.Name = "Time"
	local BestTime = Instance.new("IntValue", Leaderstats)
	BestTime.Name = "Best Time"
	Time.Changed:Connect(function()
		if Time.Value > BestTime.Value then
			BestTime.Value = Time.Value
		end
	end)
	player.CharacterAdded:Connect(function(char)
		local humanoid = char:WaitForChild("Humanoid")
		if humanoid then
			humanoid.Died:Connect(function()
				for i,v in pairs(threads) do
					if v[1] == player then
						v[2] = true
						Time.Value = 0
					end
				end
			end)
		end
	end)
end)


Region.Touched:Connect(function(hit)
	local Player = game.Players:GetPlayerFromCharacter(hit.Parent)
	if Player then
		local Leaderstats = Player:WaitForChild("leaderstats")
		if not Leaderstats then return end
		local Time = Leaderstats:WaitForChild("Time")
		if not Time then return end
		local BestTime = Leaderstats:WaitForChild("Best Time")
		if not BestTime then return end
		local Found = nil
		for i,v in pairs(threads) do
			if v[1] == Player then
				Found = v
			end
		end
		if Found == nil then
			local Thread = coroutine.create(function()
				local x = tick()
				while true do
					wait()
					for i,v in pairs(threads) do
						if v[1] == Player then
							if v[2] == true then
								Player = nil
							end
						end
					end
					if Player == nil then break end
					if tick() - x >= 1 then
						x = tick()
						Time.Value += 1
					end
				end
			end)
			table.insert(threads, {Player, false})
			coroutine.resume(Thread)
		else
			if Found[2] == true then
				for i,v in pairs(threads) do
					if v == Found then
						table.remove(threads, i)
					end
				end
			end
		end
	end
end)
1 Like