Cant Get function to happen only once

  if not hookedOnce then
                LaunchHookL.Touched:Connect(function(HookHit)
                    if HookHit:IsDescendantOf(Character) then 
                        return

                    else
                        hookWeld = Instance.new("WeldConstraint")
                        hookWeld.Parent = LaunchHook
                        hookWeld.Part0 = HookHit
                        hookWeld.Part1 = LaunchHook
                        hookedOnce = true
                    end
                end)    
            end
        end
    end
end)
UIS.InputEnded:Connect(function(unputObject)
    
    if unputObject.KeyCode == Enum.KeyCode.Q then
        hookWeld:Destroy()
        wait(1)
        hookedOnce = false
        LaunchHook:Destroy()    

this is supposed to make a grappling hook attach once, and not again after release, they fall as intended, but immediately attach to the next part i thought i set the if statement to check that? can anyone explain whats happening?

Is it because you have a wait(1) before you set the variable to false?

When you make a connection it isn’t conditional. The Touched connection is added if hookedOnce == false, and will continue receiving touched events until it is disconnected, it does not care about the hookedOnce variable.

You should move the check into the touched function like so, so you are checking at every touched event.

LaunchHookL.Touched:Connect(function(HookHit)
    if hookedOnce or HookHit:IsDescendantOf(Character) then
        return
    end
    -- etc...
end)