Scripting HelpersARCHIVE
A little piece of Roblox history. Preserved for everyone, one question at a time.Read about the archive →
COMMUNITY QUESTION

Issues with hit detection and disconnecting function?

I'm creating a combat system, and so far what I have is a player presses q to play an animation, which in turn fires an event. The event is handled in a server script in ServerScriptService, and handles the hit detection and damaging (to prevent exploiters). However, the hit detection for it seems to be very buggy when I try to disconnect the function.

-- All variables are defined prior to this code
local Touched
Touched = part.Touched:Connect(function(hit)
	local humanoid = hit.Parent:FindFirstChild("Humanoid")
	local upperTorso = hit.Parent:FindFirstChild("UpperTorso")
	if humanoid and not humanoid:IsDescendantOf(plr.Character) then
		humanoid:TakeDamage(damage)
		Touched:Disconnect() -- Disconnect the function once it's hit to prevent double hitting
		end
	end)
wait(.35) -- Wait for the animation to end, then disconnect it again (incase the character never hits anyone)
Touched:Disconnect()

The hit detection works fine without the second disconnect, except for if I press Q tons of times, it will then do tons of damage to whoever is hit next, whether or not the character is playing the animation.

Local Script

local UIS = game:GetService("UserInputService")
local player = game:GetService("Players").LocalPlayer
local character
local humanoid
local LeftPunchAnimation
local RightPunchAnimation

local PunchEvent = game:GetService("ReplicatedStorage").Events.Punch

local PowerAmount = script.Parent.SlideValue

player.CharacterAdded:Connect(function(c)
	character = c
	humanoid = c:WaitForChild("Humanoid")
	LeftPunchAnimation = humanoid:LoadAnimation(script.LeftPunch)
	RightPunchAnimation = humanoid:LoadAnimation(script.RightPunch)
end)

local punchDebounceTime = .45
local punchDefaultDamage = 5
local punchDB = false
local lastPunch = 0

UIS.InputBegan:Connect(function(input,gp)
	if gp then return end
	
	if input.KeyCode == Enum.KeyCode.Q and punchDB == false then
		punchDB = true
		if lastPunch == 0 then
			lastPunch = 1
			RightPunchAnimation:Play()
			local connect
			connect = RightPunchAnimation.KeyframeReached:Connect(function(name)
				if name == "Action" then
					PunchEvent:FireServer("Right",PowerAmount.Value)
					connect:Disconnect()
				end
			end)
		elseif lastPunch == 1 then
			lastPunch = 0
			LeftPunchAnimation:Play()
			local connect
			connect = LeftPunchAnimation.KeyframeReached:Connect(function(name)
				if name == "Action" then
					PunchEvent:FireServer("Left",PowerAmount.Value)
					connect:Disconnect()
				end
			end)
			
		end
		wait(punchDebounceTime)
		punchDB = false
	end
end)

Any help appreciated!

1 answer

You're making it more complicated than it needs to me. There's no need to disconnect the function and you could just set a debounce to prevent damage from repeating.

Server Script

-- All variables are defined prior to this code

local debounce = false -- debounce

part.Touched:Connect(function(hit)
    local humanoid = hit.Parent:FindFirstChild("Humanoid")
    if humanoid and debounce == false then -- if hit has a humanoid then...
	debounce = true
        humanoid:TakeDamage(damage)
	wait(0.35) -- waits 0.35 seconds for the animation to finish playing
	debounce = false 
        end
end)

Local Script

local UIS = game:GetService("UserInputService")
local player = game:GetService("Players").LocalPlayer
local character
local humanoid
local LeftPunchAnimation
local RightPunchAnimation

local PunchEvent = game:GetService("ReplicatedStorage").Events.Punch

local PowerAmount = script.Parent.SlideValue

player.CharacterAdded:Connect(function(c)
    character = c
    humanoid = c:WaitForChild("Humanoid")
    LeftPunchAnimation = humanoid:LoadAnimation(script.LeftPunch)
    RightPunchAnimation = humanoid:LoadAnimation(script.RightPunch)
end)

local punchDebounceTime = .45
local punchDefaultDamage = 5
local punchDB = false
local lastPunch = 0
local debounce = false -- debounce for first KeyframeReached
local debounce2 = false -- debounce for second KeyframeReached

UIS.InputBegan:Connect(function(input,gp)
    if gp then return end

    if input.KeyCode == Enum.KeyCode.Q and punchDB == false then
        punchDB = true
        if lastPunch == 0 then
            lastPunch = 1
            RightPunchAnimation:Play()
	        RightPunchAnimation.KeyframeReached:Connect(function(name)
                if name == "Action" and not debounce then
		    debounce = true
                    PunchEvent:FireServer("Right",PowerAmount.Value)
			wait(0.45)
			debounce = false
                end
            end)
        elseif lastPunch == 1 then
            lastPunch = 0
            LeftPunchAnimation:Play()
            LeftPunchAnimation.KeyframeReached:Connect(function(name)
                if name == "Action" and not debounce2 then
		    debounce2 = true
                    PunchEvent:FireServer("Left",PowerAmount.Value)
                    wait(0.45)
			debounce2 = false
                end
            end)

        end
        wait(punchDebounceTime)
        punchDB = false
    end
end)

13 comments

0

If you have any questions feel free to ask, i have yet to test this code myself but it should work fine.

0

Defining upperTorso was for a separate purpose, guess I forgot to completely remove it from the script. I know plenty about debounces, but am confused how I would incorporate that into this? If I fire the remoteevent multiple times, then multiple touched connections will be formed causing extra damage, and using the debounce will continue damaging even if the animation isn't playing.

0

Show me your local script

0

Edited it into the question

0

You need a seperate debounce for both KeyframeReached events.

0

I'll try to edit the script so gimme a minute

0

My issue isn't regarding time between punches, if that's what you mean when you say I need debounces for the both KeyframeReached events. I'm just having trouble with the touched part, as it hits sometimes, whereas it doesn't other times.

0

Alright i edited the script, see if it works now

0

Reason why you need a debounce for KeyframeReached is because when the keyframe has been reached, it will fire the RemoteEvent multiple times which is why you need the debounce.

0

Nope, works how I expected (still damages after animation has ended). https://gyazo.com/c7ac5a548744192e51ff0f5562428b93

0

It also never fired more than once, I disconnect the KeyframeReached event afterwards to prevent that.

0

Well normally i put the hit detection in the local script so i can check if the animation is playing before dealing damage, but you put the touched event in the server script so i'm not sure what can be done, sorry.

0

I put the hit detection in a server script so that exploiters can't fire the damage remote themselves and kill anyone even if they aren't being hit. Thanks for trying, though.

This discussion is preserved as it was. New answers, comments, and votes are closed.