Inconsistencies in damage over time while touching a part

Hello everyone,
im trying to create a script that damages the player over time while they are in contact with a part. Simple enough.

This particular script checks for a hitbox that is spawned and welded to the player when they enter the game, double checks to be sure we are not already ticking damage on them, then begins a while true loop that breaks when the .TouchEnded event is fired. here’s the code:

local touching = {}
function whileTouching(part)
	local reentry = false
	if part.Name == "BoundingBox" then --determine if this part is a bounding box
		if touching[part.Parent.Humanoid] == false or touching[part.Parent.Humanoid] == nil then	--check if were already tracking this humanoid
			if touching[part.Parent.Humanoid] == false then 
				reentry = true 
			end --if we are, then flag it as a reentry
			print(touching)
			touching[part.Parent.Humanoid] = true
			print("we got a live one", touching,reentry)
			if reentry == true then wait(1.25) end --if we are reentering, wait for 1.25 seconds to prevent rapidly dying upon entry and exit
			while true do
				if touching[part.Parent.Humanoid] == false then
					break 
				end --if we are no longer touching, stop the loop.
				print("this is damage")
				wait(interval)
			end
		end
	end
end

function touchEnded(part)
	if part.Parent:FindFirstChild("Humanoid") ~= nil then
		touching[part.Parent.Humanoid] = false
	end
end

script.Parent.HitBox.Touched:connect(whileTouching)
script.Parent.HitBox.TouchEnded:connect(touchEnded)

The script does function, its just incredibly inconsistent, which is making it difficult for me to find the bug. It will sometimes track a player multiple times, making it tick them with two or even three different instances. Other times it doesn’t register them at all. It will even happen when first entering the box, meaning that it likely has nothing to do with the reentry grace period.

I’ve tried everything i can think of. All of the variables involved show what youd expect them to be, every time. touching always has the player’s instance, and its always flagged as it should be. reentry is never flagged incorrectly. As far as i can tell, the code itself works perfectly fine. It just goes off inconsistently.

I’ve included a copy of an isolated instance of the object that uses the script, so you can look at it for yourself (since i had a hard time getting footage of any of this given the inconsistency)
Help.rbxl (39.1 KB)

I’m starting to believe this is a problem with .Touched. I’ve heard nebulous bad things about it in the past, but never anything specific so i thought it might be fine for this application. If .Touched is to blame, id love to hear if anyone has any alternatives.

Any and all input would be appreciated. Thank you so much for your time <3

the Touched event is only called when something moves and touches the part or the part moves while the other part is touching it. even this is very inconsistent

i suggest you switch to using a region3 and putting the damage in a loop while inside the region

or use GetTouchingParts on a loop

2 Likes

When using Touched and TouchEnded you should only account for touches from a particular part.

If a character model touches a part with four limbs its Touched event will be fired four times, if one of those limbs then stops touching the part its TouchEnded event will fire.