Touched event doesn't fire

Hi! I’m making an ability that does a heavy punch. My problem is that when the arm touches the other player it doesn’t work. But sometimes there is a small chance for it to work.

Script

local touched = false
game.ReplicatedStorage.AbilityUse.OnServerEvent:Connect(function(plr)
	plr.Character.Humanoid.WalkSpeed = 4
	plr.Character.Humanoid.JumpHeight = 0
	local CombatHeavy = plr.PlayerGui.Animations:WaitForChild("CombatHeavy")
	local CombatHeavyAnim = plr.Character.Humanoid:LoadAnimation(CombatHeavy)
	CombatHeavyAnim:Play()
	wait(0.5)
	plr.Character["Right Arm"].CanTouch = true
	plr.Character["Right Arm"].Touched:Connect(function(hit)
			if hit.Parent:FindFirstChild("Humanoid") and hit.Parent ~= plr.Character then
				if hit.Parent.Humanoid.Health > 0 then
					if not touched then
						touched = true
						plr.Character["Right Arm"].CanTouch = false
						local PunchSFX = Instance.new("Sound")
						PunchSFX.Name = "CombatHeavy"
						PunchSFX.RollOffMaxDistance = 150
						PunchSFX.RollOffMinDistance = 1
						PunchSFX.RollOffMode = Enum.RollOffMode.Linear
						PunchSFX.Parent = plr.Character.HumanoidRootPart
						PunchSFX.SoundId = "rbxassetid://7346569653"
						PunchSFX:Play()
						local target = hit.Parent
						local joints = target:GetDescendants()
						target.Humanoid.Health = target.Humanoid.Health - 18
						target.HumanoidRootPart.Velocity = plr.Character.HumanoidRootPart.CFrame.LookVector * 300 + Vector3.new(0,300,0)
						for _,joint in pairs(joints) do
							if joint:isA("Motor6D") then						
								local socket = Instance.new("BallSocketConstraint")
								local att0 = Instance.new("Attachment")
								local att1 = Instance.new("Attachment")
								print(joint)
								target.Humanoid:ChangeState(Enum.HumanoidStateType.Physics)
								target.Humanoid:SetStateEnabled(Enum.HumanoidStateType.GettingUp, false)
								target.Humanoid.AutoRotate = false
								--target.Humanoid.PlatformStand = true
								--target.Humanoid.WalkSpeed = 0
								--target.Humanoid.JumpPower = 0
								att0.Name = "Att0"
								att1.Name = "Att1"
								att0.CFrame = joint.C0
								att1.CFrame = joint.C1
								att0.Parent = joint.Part0
								att1.Parent = joint.Part1
								
								
			
								socket.Parent = joint.Part0
								socket.Attachment0 = att0
								socket.Attachment1 = att1
								att0.Name = "Att0"
								att1.Name = "Att1"
				
				
								socket.LimitsEnabled = true
								socket.TwistLimitsEnabled = true
					
								--wait(0.2)
				
								--wait(2)
				
								joint.Enabled = false
								
							end
						end
						if hit.Parent.Humanoid.Health > 0 then
							if target.Name ~= "Dummy3" then
								target.Humanoid:ChangeState(Enum.HumanoidStateType.GettingUp)
								target.Humanoid:SetStateEnabled(Enum.HumanoidStateType.GettingUp, true)
								target.Humanoid.AutoRotate = true
								target.Humanoid.WalkSpeed = 26
								target.Humanoid.JumpPower = 7.5
								for _,joint2nd in pairs(joints) do
									if joint2nd:isA("Motor6D") then
										joint2nd.Enabled = true
									end	
								end
								for _, child in pairs(target:GetDescendants()) do
									if child.Name == "Att0" or child.Name == "Att1" or child:IsA("BallSocketConstraint") then
										child:Destroy()
									end	
								end
							end
						end
					end			
				end	
			wait(2)
			plr.Character.Humanoid.WalkSpeed = 26
			plr.Character.Humanoid.JumpHeight = 7.2
			touched = false
			wait(2)
		end
	end)
end)

This is the code that doesn’t work:

plr.Character["Right Arm"].Touched:Connect(function(hit)

Any help appreciated.

It could be that it has a very bad detection, you should consider using :GetPartsInPart()

1 Like

Would it then look like this plr.Character:GetPartsInPart(["Right Arm"]).Touched:Connect(function(hit)?

Also the “Right Arm” is inside a player model not a part.

No, search up Overlap Params. It should be something like this.

local OP = OverlapParams.new()
local RightArm = ...
local Hit = game.Workspace:GetPartsInPart(RightArm, OP)

You just gonna have to loop “Hit” and check for collision with a for i loop. Best to return the function if the table length is 0.

I’m pretty sure character parts have no spaces.
plr.Character.RightArm.Touched:Connect(function(hit))
I could be dumb though, but make sure to check the part names of R6 players while playtesting.

They do. I tried making that mistake the first time and then I looked inside my character model and it had spaces.

OH MY GOD! That’s so strange! Have you tried printing after the touched event, or testing other parts? And try Humanoid.Touched to test if it’s the event’s fault.
EDIT: I just realised you probably already printed after touch…

To simplify what @KultDeeri says, the .Touched() event doesn’t always fire when the part moves too fast, because the engine itself doesn’t notice a touch that small.

:GetPartsInPart() is a different function that returns a list of every part that touches your part. You could check for this in the Fist part (local hits = plr.Character["Right Arm"]:GetPartsInPart() and then loop through the “hits”). The problem with this is that you have to check for touching parts multiple times as fast as possible until the animation is over for it to be accurate. That might complicate things.

Instead, I recommend creating a hitbox in front of the character and only checking that once. You can just create a part (CanCollide and Anchored false), weld it to the character and make it as big as you want the player’s “reach” to be. Basically, this part will be the hit detection, so when the player punches, every other player that is inside this part or just touches it will get punched by the player. For this you can just use the GetPartsInPart() once, when the player punches. Then loop through the parts and get every player that is inside it (make sure to only detect every player once and to blacklist the player that punches so they can’t hit themselves).

I’m sure there are tutorials on the internet on how to do this if my explanation wasn’t clear enough.
Hope this helps!