Loop running more than once?

Basically I’m trying to make a push tool but I’ve come across a problem. I don’t want to use .Touched as it’s so goddamn unreliable, so I’m using an alternative(:GetPartsBoundInBox()), but that requires a loop and unfortunately a loop inside an event makes it run more than once so I get stuff like this happening:


Every other .Touched alternative I’ve found uses a loop, so how do I ensure a loop inside an event doesn’t run more than once.

local animid = "rbxassetid://132154288943189"
local debounce = false
local cooldown = 1.5
local counter = 0
local conn
function animate(char)
	if debounce == false then
		local animation = Instance.new("Animation")
		animation.AnimationId = animid
		local anim = char.Humanoid.Animator:LoadAnimation(animation)
		anim:Play()
	end
end
function push(humanoid, char)
	print("aa")
	if debounce == true then return end
	if humanoid then
		local opposition = humanoid.Parent
		local hrp = opposition.HumanoidRootPart
		hrp.CFrame = hrp.CFrame * CFrame.Angles(90,0,0)
		hrp.AssemblyLinearVelocity = Vector3.new(0,0,-100)
	end
	animate(char)
debounce = true
	task.wait(cooldown)
	debounce = false
end

conn = script.Parent.Activated:Connect(function()
	local char = script.Parent.Parent
	local hitbox = char:WaitForChild("Hitbox")
	local params = OverlapParams.new()
	params.FilterDescendantsInstances = {
		hitbox,
		char["Right Leg"],
		char["Left Leg"],
		char["Left Arm"],
		char["Right Arm"],
		char.Head,
		char.Torso,
		char.HumanoidRootPart
	}
	print("actu")
	local parts = workspace:GetPartBoundsInBox(hitbox.CFrame, hitbox.Size, params)
		for i,v in pairs(parts) do
			print(v.Name)
			print(v.Name)
			if v.Name == "Block" then
				return
			end
			push(v.Parent:FindFirstChild("Humanoid"), char)
	end
end)

Yes this script is insanely messy

2 Likes

you forgot to add ‘end’ at:

for i,v in pairs(parts) do
			print(v.Name)
			print(v.Name)
			if v.Name == "Block" then
				return
			end
			push(v.Parent:FindFirstChild("Humanoid"), char)

I did and if I didn’t the whole script would error

use a debounce array and store the characters that is processed.

usually you will find from the hitted part, search up to the nearest ancestor Model as it is the root of the player character.

then if in next loop cycle, the character exists in the array, you skip it.

after a cooldown or some criteria, you can clear the whole debounce array or only remove that character

I tried this and the problem persisted, the loop will still run the action more than once and as the table is cleared afterwards, it doesn’t do much.
Also I would want the table to be cleared afterwards to not give a random player immunity.

You could use :Once() instead of :Connect() and when the loop is finished you connect again the function with :Once() !
Hope this helped, have a nice day !

How would I go about connecting the function again?

1 Like

Hi! Maybe add break after calling push function?

1 Like

make sure you use task.spawn to run the push() in parallel. without the spawn, it processed the hit, then wait, then clear debounce table, THEN process the next hitted object.
while what you want is the process all the hitted parts at the same time, THEN wait, then clear debounce table

to stop the looping pushing you need to break out of your for loop after you call the push function

for i,v in pairs(parts) do
	print(v.Name)
	print(v.Name)
	if v.Name == "Block" then
		continue -- and you may want to change this return to continue
	end
	push(v.Parent:FindFirstChild("Humanoid"), char)
	break -- need to stop this loop after push is called
end

you may also want to change the break in the block if statement to continue so your loop will go to the next part

1 Like

Problem with this is if I’m not mistaken wouldn’t the loop only loop once. So like lets say there’s multiple parts in the hitbox, wouldn’t it only choose one part instead of looking through all of them?

Why you need to look through all of them?
Push function adds assembly velocity only on HumanoidRootPart

Lets say there’s a non character part along with character parts in the hit box and as it can only check once, it chooses to check that one. It won’t push the character even though they’re in the hitbox

In this case i think will be better to do this:

for i,v in pairs(parts) do
	print(v.Name)
	print(v.Name)
	if v.Name == "Block" then
		return
	elseif v.Name == "HumanoidRootPart" then
		push(v, char)
		break
	end
end

Can you mark post as solution if it helped you?

i tried this and it worked fine for me when i put the character that is in the hitbox into a table and then checked whether or not if the bodypart that was in the hitbox is from that character, and if it is i dont push again since it already got pushed using that hitbox

Yes thank you so much (character limit)

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.