Problem with raycasting on unanchored parts

So I’ve coded a gun, which casts a ray to the player’s mouse, and detects if it hits a humanoid, which is pretty simple. It works pretty good so far, however there was one strange issue that I ran into.

I’ve also created a zombie AI. When I shoot the zombie’s head or torso with my gun, it deals the proper amount of damage it’s supposed to. But for some reason, the raycast can’t seem to hit the arms or legs?? I’ve tried to print the raycast, and whenever I aim directly at the legs/arms, it always says “nil”.

What’s even weirder is that when I anchor any part of the zombie, I am for some reason able to shoot the arms and legs and it works like it’s supposed to. Any help would be greatly appreciated!

2 Likes

How is the zombie being animated? Are you doing client-sided or server-sided animations?

1 Like

Can I see the part of your code where you ray cast? Make sure to include all the way to where it damages too.

I’m using server-sided animations.

      eventsFolder.Fire.OnServerEvent:Connect(function(player, mousePos, mouseTarget)
if not cooldown then
	if ammo.Value >= 1 then
		ammo.Value -= 1
		cooldown = true
		spawn(function()
			wait(gunSettings.firerate)
			cooldown = false
		end)
		script.Events.CameraFlick:FireClient(player, gunSettings.recoil)
		muzzleFlash()
		animations.Fire:Play()
		
		if fireSoundNum == 1 then
			fireSoundNum = 2
			sounds.Fire1:Play()
		elseif fireSoundNum == 2 then
			fireSoundNum = 1
			sounds.Fire2:Play()
		end
		local spread = Vector3.new(math.random(-gunSettings.spread, gunSettings.spread), math.random(-gunSettings.spread, gunSettings.spread), math.random(-gunSettings.spread, gunSettings.spread)) / 10
		
		local rParams = RaycastParams.new()
		rParams.RespectCanCollide = true
		rParams.FilterDescendantsInstances = {character, weapon}
		rParams.FilterType = Enum.RaycastFilterType.Blacklist
		local ray = workspace:Raycast(weapon.Frame.BulletExit.WorldPosition, ((mousePos + spread) - weapon.Frame.BulletExit.WorldPosition).Unit * 5000, rParams)	
		
		if ray ~= nil then
			if ray.Instance ~= nil then
				local hit = ray.Instance
				if hit.Parent:FindFirstChildWhichIsA("Humanoid") then
					rParams.FilterDescendantsInstances = {character, weapon, ray.Instance.Parent}
					local ray2 = workspace:Raycast(mousePos + spread, weapon.Frame.BulletExit.WorldPosition - (mousePos + spread), rParams)
					if ray2 == nil then
						local hum = ray.Instance.Parent:FindFirstChildWhichIsA("Humanoid")
						local damage = damageSettings.other
						print(hit)
						if hit.Name == "Head" then
							damage = damageSettings.head
							playHitSound(hit, sounds.bulletImpact.HeadShot)
						elseif string.match(hit.Name, "Torso") or hit.Name == "HumanoidRootPart" then
							damage = damageSettings.torso
							playHitSound(hit, sounds.bulletImpact.TorsoShot)
						elseif string.match(hit.Name, "Arm") or string.match(hit.Name, "Leg") then
							playHitSound(hit, sounds.bulletImpact.LimbShot)
							damage = damageSettings.limb
						else
							playHitSound(hit, sounds.bulletImpact.MiscShot)
						end
						bloodSplatter(ray.Position)
						hum:TakeDamage(damage)
						
						if hum.Health <= 0 and hit.Name == "Head" then
							local bv = Instance.new("BodyVelocity")
							bv.P = math.huge
							bv.MaxForce = Vector3.new(math.huge, math.huge, math.huge)
							bv.Velocity = hit.CFrame.LookVector * -30
							bv.Parent = hit
							game.Debris:AddItem(bv, 0.2)
							hit.Parent.Torso.Neck:Destroy()
						end
						if damageSettings.bleeding then
							spawn(function()
								wait(0.5)
								for i = 1, math.random(5, 9), 1 do
									if hum.Health > 0 then
										bloodSplatter(hit.Position)
										hum:TakeDamage(damage * damageSettings.bleedPercentage)
										wait(0.8)
									end
								end
							end)
						end
					end
				else
					hitResidue(ray.Position, hit.Color)
				end
			end
		end
		
	end
end
 end)

messy code, but it does the job haha

Can you explain why you have two raycasts? I’m confused on what you’re trying to do with that.

I dont think it has anything to do with the problem, but heres why: A raycast wont detect a part if it is raycasted inside of that part. So if a player puts their gun inside of a wall, then they could shoot through that wall. I use a second ray to cast back from where the first ray hit to make sure that there are no parts intersecting with the gun and the target.

Well, the fact that it’s even printing nil when you shoot the arms means that the ray cast is detecting the left arm, since it will only get to that part if ray.Instance ~= nil. There must be something going on after that line, so try printing to the output right after that conditional statement to see if the part really is nil, or if there’s something causing that part to go nil in the client. I’m guessing this piece of code is placed in a local script, so it might have to do something to do with server-client replication.

Since something is causing the part to become nil even though the part shouldn’t be nil according to the conditional statement, that means the second ray cast could indeed have something to do with the issue.

But I’m not quite sure why when I anchor a part of the zombie, the raycast is able to able to hit the limbs all of the sudden and works properly?

When you anchor the character, you’re anchoring the character on the client, but not on the server. This is why the code suddenly works, because now the part you’re working with is going to stay the exact same on the client. I’m guessing that’s where the problem stems from, but it could definitely be something else.

Edit: Anchoring on the server should do the same thing. The character is no longer moving, so the limbs aren’t changing anymore, and there can’t be any server-client replication issues when the parts aren’t even changing.

Ah I see, but I still don’t know how to fix it. (the script that i sent was a server script btw)