Reconnecting a .touched event after disconnecting it just makes an infinite loop (idk what the title should be)

I just want to know why does this make a infinite loop when connected to a part that had previously ran this code?

	local function BlockTouched()
		print("Touched")
		local Vel=Block.AssemblyLinearVelocity.Magnitude
		if Vel>7 then
			Block:SetAttribute("Health",Health-Vel/10)		
			HeartBeat:Wait()task.wait(.07)HeartBeat:Wait()
		else
			HeartBeat:Wait()task.wait(.3)HeartBeat:Wait()
		end
		Block.Touched:Once(BlockTouched)
	end
	Block.Touched:Once(BlockTouched)

Edit: Im aiming to disconnect the event and then reconnect it after a set amount of time

notice how at the end of the function, it connects the function to the touched event (again)

So it’s essentially recursive (it’s a function that calls itself). And it’ll keep doing this infinitely til you stop it

3 Likes

from my understanding,
you need a debounce or a bool value that will lock the function outside the block of code from activating the function again

also why do you need to call the event inside the function again? (The person above tells you why)

This will probably fix it!

local IsProcessing = false

local function BlockTouched()
	if IsProcessing then return end
	IsProcessing = true -- Lock the function

	print("Touched")
	local Vel = Block.AssemblyLinearVelocity.Magnitude
	if Vel > 7 then
		Block:SetAttribute("Health", Health - Vel / 10)		
		HeartBeat:Wait()
		task.wait(0.07)
		HeartBeat:Wait()
	else
		HeartBeat:Wait()
		task.wait(0.3)
		HeartBeat:Wait()
	end

	IsProcessing = false -- Unlock the function
end

Block.Touched:Connect(BlockTouched)
1 Like

This is just a gamble the right part will touch first.
Heartbeat and Stepped is way too fast to be used as a pause. (in my opinion)
Try a larger task.wait().

dxxmed has your fix.

1 Like

So this debounces the code and prevents it from making a new thread for the same function while the prevoius thread was running. But the thing is eatch time the game fires the touched event it has to check the IsProcessing == false which could lead to a memory leak or something

I am aiming to disconnect the event and reconnected after an set time had passed (i forgot to say that in the OP)

It does an infinite loop because you have a recursive function that constantly call itself. You have to remove: Block.Touched:Once(BlockTouched) inside the function.

If you need the ability to touch the block multiple times, you should use :Connect(), instead of :Once().

Also, the task library is already synchronized with Heartbeat so your hearbeat wait are useless.

local TouchReady = true

local function BlockTouched()
    if TouchReady == false then
        return
    end

    TouchReady = false
	if Block.AssemblyLinearVelocity.Magnitude > 7 then
		Block:SetAttribute("Health", Health - Vel / 10)
		task.wait(0.07)
	else
		task.wait(0.3)
	end
    TouchReady = true
end

Block.Touched:Connect(BlockTouched)

Stepped is now deprecated, you should use PreSimulation instead.

1 Like

what about :BindToRenderStep?

1 Like

Isnt that only on the client. Im running the script on the server

Edit: The extra HeartBeat in my mind serves as an extra throttler (a delay that gets bigger when the game lags)

image

I think it’s still fine to use BindToRenderStep, there is no replacement for that yet.
It’s only about Stepped and RenderStepped.

then wouldn’t this work? you can use pcall or coroutine.wrap for further protection (unexpected errors)

local HeartBeat = game:GetService("RunService").Heartbeat
local Health = Block:GetAttribute("Health") or 100 
local connection -- to hold the connection reference

local function BlockTouched(otherPart)
    -- Immediately disconnect event to prevent re-entry
    connection:Disconnect()

    print("Touched")
    local Vel = Block.AssemblyLinearVelocity.Magnitude
    if Vel > 7 then
        Block:SetAttribute("Health", Health - Vel / 10)
        HeartBeat:Wait()
        task.wait(0.07)
        HeartBeat:Wait()
    else
        HeartBeat:Wait()
        task.wait(0.3)
        HeartBeat:Wait()
    end

    -- Reconnect the event after processing and waiting period
    connection = Block.Touched:Connect(BlockTouched)
end

-- Initially connect the event
connection = Block.Touched:Connect(BlockTouched)


1 Like

:cry: :cry: “lobotomized behemoth” :sob: thats so sad

2 Likes

What! This is one of the best commands in the language.

The PreRender event (replacement for RenderStepped)
Oh they have one for you too :rofl:

This works. I have fixed it

	
	local MinBlockDamageVel=16 
	
	local CanTouch=false
	local TouchConnection=nil
	local function BlockTouched(Hit:BasePart)
		local Vel=Block.AssemblyLinearVelocity.Magnitude
		if Hit.AssemblyLinearVelocity.Magnitude>Vel then
			Vel=Hit.AssemblyLinearVelocity.Magnitude
		end
		if Vel>7 then
			Block:SetAttribute("Health",Health-Vel/5)
			local h=Hit:GetAttribute("Health")
			if h then
				Hit:SetAttribute("Health",h-Vel/5)
			end
		end
		if CanTouch==true then
			HeartBeat:Wait()task.wait(.15)
			TouchConnection=Block.Touched:Once(BlockTouched)
		end
	end
	
	local function CheckBlockVel()
		if Block.AssemblyLinearVelocity.Magnitude>MinBlockDamageVel then
			CanTouch=true
			if TouchConnection==nil then
				TouchConnection=Block.Touched:Once(BlockTouched)
			end	
		else
			CanTouch=false
			if TouchConnection~=nil	then
				TouchConnection:Disconnect()
				TouchConnection=nil
			end
			task.wait(.1)
		end
		task.wait(.3)
		HeartBeat:Once(CheckBlockVel)
	end
	HeartBeat:Once(CheckBlockVel)

What do you mean by this?
Heartbeat fires at the end of the physics simulation every frame (equivalent to the newer PostSimulation)

You’re right, I said that backwards…

Stepped: Timing, Before physics simulation. Happens after, Last frame render.
Heartbeat: Timing, After physics simulation. Happens after, Physics & internal sim.

Stepped: Good for logic that affects physics.
Heartbeat: Good for logic that reacts to physics.

In this case I don’t really think any of that comes into play, as a pause. I should have said, just use a longer task.wait().

I changed the post for you.

“Stepped is now deprecated”… I had to do some research on that.

Roblox introduced new frame phase events to give more precise control over timing. They are not replacements, but lower-level alternatives for specific use cases.

1 Like

They are indeed replacements.

This event has been superseded by PreSimulation which should be used for new work.

what you are trying to do WILL memory leak, the debouce/cooldown approach by keisac is actually the way to go, is there any particular reason why you want to disconnect and then reconnect?

1 Like