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)
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 !
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
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?
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
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
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