Touched not firing for a part sometimes

I’m currently working on a game where you jump on enemies to damage them, and when you jump on them, you also get an extra jump, like in Super Mario. However, I’m using the touched event on a part welded to the enemy’s root part (the enemy is a humanoid) to detect when a player touches it, and 25% of the time, the player does not get a slight jump after jumping on the enemy, and I’ve figured out that it’s the touched event not firing on the part welded to the enemy’s root.

Here’s the code that’s in a local script, but I’m certain it’s safe:

hitbox.Touched:Connect(function(hit) --The hitbox here is a part welded to the player's root to detect jumping on enemies
		print("debounce:", debounce, "attr:", hit.Parent:GetAttribute("Damage"), "health:", hit.Parent.Humanoid.Health, "name:", hit.Name, "ancest:", hit:FindFirstAncestor("Enemies"))
		--Here we check if the player hit a part welded to the enemy's root
		if not debounce and hit:FindFirstAncestor("Enemies") and not hit.Parent:GetAttribute("Damaged") and hit.Name == "JumpHitbox" and hit.Parent.Humanoid.Health > 0 then
			debounce = true
			print("set to true")
			local pos = root.Position.Y
			--Don't worry about this stuff
			for i = 1, 3 do
				runService.RenderStepped:Wait()
			end
			print("waited for a few frames")
			print(pos - root.Position.Y)
			if math.sign(pos - root.Position.Y) == 1 then
				humanoid:ChangeState(Enum.HumanoidStateType.Jumping)
				canDoubleJump = true
				print("just jumped")
			else
				print("did not jump")
			end
			print("gonna set to false")
			wait(.3)
			print("set to false")
			debounce = false
		end
	end)

I’m 100% positive that this code is fine. I’ve tested it, and whenever the player doesn’t jump after jumping on the enemy, nothing in the event runs.

Here is a picture of the enemy dummy. I’ve selected both the enemy’s root and the part welded to the root. The part welded to the root has CanTouch on, but the root doesn’t. This property is not changed by any other scripts.

  1. What do you want to achieve? I want to make the player jump after jumping on an enemy.

  2. What is the issue? 25% of the time, the touched event doesn’t fire when the player touches the part welded to the enemy’s root.

  3. What solutions have you tried so far? I tried detecting the enemy’s root instead of the part welded to the root, and had the same issue. I also tried looking up a similar issue. Nothing.

The thing is, I also check the player jumping on the enemy on the server (so I can damage it on the server) and it’s perfectly fine there, but why not here? It has pretty much the exact same code as the LocalScript I showed, so I’m completely stumped.

Also, the enemy’s root and the part welded to the root only change position when the server temporarily adds a body position in it, but quickly destroys the body position afterwards. I doubt this has any relevancy to the issue at hand, but just clarifying that the root’s position and the part welded to the root’s position never really change.

Touched can be very tricky at times so I would suggest using raycasting.

But you said the touched event only fires rarely? I would suggest having the hitbox more out of the chest else its harder for a player character to hit it, especially r15.

Also I’m not totally sure about using local scripts for something like that, incase you were ever trying to mark stats you’d have to use a remote event making it extremely susceptible to exploiters.

How would raycasting work here? That’s a pretty good idea, but how should I use it here?

I’ve never done something like this so this will most likely be unoptimized, but I would have it check whenever they got in a certain radius using Magnitude and then fire the raycast above the enemy head everytime the player jumped or something along those lines.

Oh right, theres also Humanoid:GetState() which I think would be perfect for what you’re trying to do

Humanoid:getState() wouldn’t work too well because I have to detect if the player did not jump while their character is inside the enemy (that’s what the confusing code above was for:

local pos = root.Position.Y
--Don't worry about this stuff
for i = 1, 3 do
    runService.RenderStepped:Wait()
end
print("waited for a few frames")
print(pos - root.Position.Y)
if math.sign(pos - root.Position.Y) == 1 then

Anyways, tried raycasting by casting a ray at every side and corner and middle of the enemy’s hitbox, see if the player was above it slightly, but it didn’t work. Here’s the code if you’re curious:

coroutine.wrap(function()
		while char.Parent do
			for _, enemy in pairs(enemies:GetChildren()) do
				local enemyHitbox = enemy:WaitForChild("JumpHitbox")
				local x = enemyHitbox.Size.X / 2
				local z = enemyHitbox.Size.Z / 2
				for xPos = -x, x, x / 2 do
					for zPos = -z, z, z / 2 do
						local origin = enemyHitbox.CFrame:ToWorldSpace(CFrame.new(xPos, 0, zPos)).Position
						local lookVector = (origin + Vector3.new(0, 1, 0) - origin) * 10
						local result = workspace:Raycast(origin, lookVector, params)
						if result and result.Instance == hitbox then
							if (result.Position - origin).Magnitude < .1 then
								humanoid:ChangeState(Enum.HumanoidStateType.Jumping)
								canDoubleJump = true
								print("just jumped")
								wait(.3)
								break
							end
						end
					end
				end
				runService.RenderStepped:Wait()
			end
			runService.RenderStepped:Wait()
		end
	end)()

I’m sure it isn’t too performant anyway. I’d rather use the touched event since it’s better than a loop.

Yeah, touched still works. I think there may be some other options you have but good luck with your game :+1:

.Touched and .TouchEnded can be unreliable sometimes, for example when it comes to jumping/feet. There are scenarios however when they are just convenient and using something else would be worthless.

If the CanCollide property of the hitbox is on, turning it off could solve this. It probably doesn’t work sometimes due to not registering a touch with the feet/legs because of a particular positioning or what have you. Making the hitbox slightly taller/higher than the root part should also help.

Tried all of those, and nothing worked. I’m also only checking a part welded to the player and not any feet or other limbs, if it helps.

I’m currently trying out the raycasting method again, but if it doesn’t work I’ll be out of options.

Use raycasting in the head like the other guy said!