Raycasting Mouse.Hit.p for gun system not working

You can write your topic however you want, but you need to answer these questions:

  1. What do you want to achieve? I’m working on a gun system, and I’m using raycasting to detect whether there is a part, and if there is, it changes the script so that I can’t shoot through walls, sometimes it just doesn’t work, and it also offsets the bullet to the left or right randomly, though it looks up every time if it does find a part.
  2. I looked on the devforum, but didn’t really find anything, and I’m running out of options.

Here is the relevant code.

RemoteEventFire.OnServerEvent:Connect(function(plr, MouseClickPos, BulletPartSignifierPos, Damage, HeadShotDamage)
	
	local function FireBullet()
		local rayOrigin = BulletPartSignifierPos
		local rayDirection = MouseClickPos

		local raycastParams = RaycastParams.new()
		raycastParams.FilterDescendantsInstances = {Parent.Parent.BulletPartSignifier, Parent}
		raycastParams.FilterType = Enum.RaycastFilterType.Blacklist
		local raycastResult = workspace:Raycast(rayOrigin, rayDirection, raycastParams)
		
		if raycastResult then
			
			for i, v in pairs(WorkspaceChildren) do
				if raycastResult.Instance == v then
					print("In Workspace!!!")
					local bullet = Instance.new("Part")
					bullet.Name = "Bullet"
					bullet.CanCollide = false
					bullet.Anchored = true	
					bullet.BrickColor = BrickColor.new("New Yeller")
					bullet.Material = Enum.Material.Neon
					bullet.Parent = workspace
					local Center = (raycastResult.Position + BulletPartSignifierPos) / 2
					bullet.Size = Vector3.new(0.01, 0.01, (BulletPartSignifierPos - raycastResult.Position).Magnitude)
					bullet.CFrame = CFrame.lookAt(Center,raycastResult.Position)
					if raycastResult.Instance.Parent:FindFirstChild("Humanoid") and raycastResult.Instance.Name == "Head" then
						raycastResult.Instance.Parent:FindFirstChild("Humanoid"):TakeDamage(HeadShotDamage)
						print("Humanoid")
					elseif raycastResult.Instance.Parent:FindFirstChild("Humanoid") then
						raycastResult.Instance.Parent:FindFirstChild("Humanoid"):TakeDamage(Damage)
						print("Humanoid")
					end
					wait(0.05)
					bullet:Destroy()
				end
			end
			
		else 
			print("NotFoundPart")
			local bullet = Instance.new("Part")
			bullet.Name = "Bullet"
			bullet.CanCollide = false
			bullet.Anchored = true	
			bullet.BrickColor = BrickColor.new("New Yeller")
			bullet.Material = Enum.Material.Neon
			bullet.Parent = workspace
			local Center = (MouseClickPos + BulletPartSignifierPos) / 2
			bullet.Size = Vector3.new(0.01, 0.01, (BulletPartSignifierPos - MouseClickPos).Magnitude)
			bullet.CFrame = CFrame.lookAt(Center, MouseClickPos)
			
			bullet.Touched:Connect(function(hit)
				if hit.Parent:FindFirstChild("Humanoid") and hit.Name == "Head" and not hit.Parent.Name == plr.Name then
					hit.Parent:FindFirstChild("Humanoid"):TakeDamage(HeadShotDamage)
				elseif hit.Parent:FindFirstChild("Humanoid") and not hit.Parent.Name == plr.Name then
					hit.Parent:FindFirstChild("Humanoid"):TakeDamage(Damage)
				end
			end)
			
			
			wait(0.05)
			bullet:Destroy()
		end
	end
	
	FireBullet()
	

end)

What can I do to fix these problems?

1 Like

Can we please have the relevant client code as well? your passing all the location values into the server event.

plr is the Player.
MouseClickPos is Mouse.Hit.P, the Vector3 location in the workspace.
BulletPartSignifierPos is the position of the part where I want the bullet to originate from,

Damage, HeadShotDamage (Just number values and have no real reference)

This is the client part for shooting.

Mouse.Button1Down:Connect(function()
	LeftButtonReleased = false
	if GunEquipped == true and Idle == false and OutOfAmmo == false and Firing == false and MuzzleBlast == true then
		if AutomaticWeapon == true then
			while true do
				Firing = true
				script.Shooting:Play()
				RemoteEventFire:FireServer(Mouse.Hit.p, BulletPartSignifier.Position, Damage, HeadShotdamage)
				MagAmmo = MagAmmo - 1
				CurrentAmmoGUI.Text = MagAmmo
				if MagAmmo <= 0 then
					OutOfAmmo = true
				end
				wait(FireRate)
				Firing = false
				script.Shooting:Stop()
				if LeftButtonReleased == true or OutOfAmmo == true or Idle == true then
					break
				end
			end
			
		elseif AutomaticWeapon == false then
			Firing = true
			script.Shooting:Play()
			RemoteEventFire:FireServer(Mouse.Hit.p, BulletPartSignifier.Position, Damage, HeadShotdamage)
			MagAmmo = MagAmmo - 1
			CurrentAmmoGUI.Text = MagAmmo
			if MagAmmo <= 0 then
				OutOfAmmo = true
			end
			wait(FireRate)
			Firing = false
			script.Shooting:Stop()
		end
	end
end)

Also try and set up a precision test where you click a tiny block to see if it is the ray or the part.

So I tested it, and it seems just to looking up and to the right, I click on the part sometimes, and it doesn’t return an instance, so I’m assuming it’s the ray, I likely need to modify the mouse position that I provided it to fix it, but is there anything I could do to fix it?

Little thing.


I had it print the raycast result and the Mouse Position, and it just moves it up heavily…

I might have an answer, In your server script you have the RayDirection set as just the mouse hit position, you should try it

local rayDirection = (rayOrigin - MouseClickPos)

or the other way around (mouseclickpos - rayorgin)
i forget maths because im stupid

1 Like

fidjsfujdsjufds It works! Okay, thank you. And then we have one other problem, damaging. I believe the problem is that when shooting Humanoids, it can only collide with the HumanoidRootPart, is this because CanCollide is turned on* for limbs? If so, I will change it with a character script.

When I damage a humanoid, it returns this and never anything else, so I’m assuming that is the reason.

Raycasts can affect non cancollide blocks
I noticed a few things that can be more efficient with your code

  • you loop through everything in the workspace when

  • you should create the bullet outside of the hit test so you arent repeating code

But the problem I have is it doesn’t raycast properly sometimes, and so I keep that there as a safeguard/pre-caution, because if it doesn’t find anything, then it just won’t shoot at it.

just test if raycastResult.Instance doesnt equal nil, also why do you use a block.Touched event to detect a hit?

try something like this

RemoteEventFire.OnServerEvent:Connect(function(plr, MouseClickPos, BulletPartSignifierPos, Damage, HeadShotDamage)

	local function FireBullet()
		local rayOrigin = BulletPartSignifierPos
		local rayDirection = MouseClickPos - rayOrigin

		local raycastParams = RaycastParams.new()
		raycastParams.FilterDescendantsInstances = {Parent.Parent.BulletPartSignifier, Parent}
		raycastParams.FilterType = Enum.RaycastFilterType.Blacklist
		local raycastResult = workspace:Raycast(rayOrigin, rayDirection, raycastParams)

		if raycastResult and raycastResult.Instance then
			local bullet = Instance.new("Part")
			bullet.Name = "Bullet"
			bullet.CanCollide = false
			bullet.Anchored = true	
			bullet.BrickColor = BrickColor.new("New Yeller")
			bullet.Material = Enum.Material.Neon
			bullet.Parent = workspace
			local Center = (raycastResult.Position + BulletPartSignifierPos) / 2
			bullet.Size = Vector3.new(0.01, 0.01, (BulletPartSignifierPos - raycastResult.Position).Magnitude)
			bullet.CFrame = CFrame.lookAt(Center,raycastResult.Position)
			if raycastResult.Instance.Parent:FindFirstChild("Humanoid") and raycastResult.Instance.Name == "Head" then
				raycastResult.Instance.Parent:FindFirstChild("Humanoid"):TakeDamage(HeadShotDamage)
				print("Humanoid")
			elseif raycastResult.Instance.Parent:FindFirstChild("Humanoid") then
				raycastResult.Instance.Parent:FindFirstChild("Humanoid"):TakeDamage(Damage)
				print("Humanoid")
			end
			wait(0.05)
			bullet:Destroy()

	else 
		print("NotFoundPart")
		local bullet = Instance.new("Part")
		bullet.Name = "Bullet"
		bullet.CanCollide = false
		bullet.Anchored = true	
		bullet.BrickColor = BrickColor.new("New Yeller")
		bullet.Material = Enum.Material.Neon
		bullet.Parent = workspace
		local Center = (MouseClickPos + BulletPartSignifierPos) / 2
		bullet.Size = Vector3.new(0.01, 0.01, (BulletPartSignifierPos - MouseClickPos).Magnitude)
		bullet.CFrame = CFrame.lookAt(Center, MouseClickPos)


			wait(0.05)
			bullet:Destroy()
		end
	end

	FireBullet()


end)

Wait. No, it does work. My brain is tired.

Using the code that I have.

It just sometimes doesn’t register a hit, and I have no clue why it isn’t working, it just isn’t working. https://gyazo.com/c03cf117038549f79e5860621e341922

instead of doing

print("PartNotFound")

do

print(raycastResult.Instance)

so it will accurately tell you what it is hitting

Also i think its because the Ray is not extending, your mouse hit position might be a little behind what you do

try putting this in

local function FireBullet()
		local rayOrigin = BulletPartSignifierPos
		local rayDirection = ((MouseClickPos - rayOrigin).Unit) * 1000
		--Unit sets the direction to do one stud
		--Replace 1000 with the range you want
3 Likes

I don’t know what particularly fixed it, but it works fully. Thank you very much. If the devforum added awards like reddit, I’d give one, lol.

thanks, what fixed it was the mouse hit position was just shy of the actual target so it stopped before it hit, I made it so the Vector3 direction would be 1 stud, then you multiply it by the range you want.

Like a rocket like or that helper award thing? yeah that would be cool. (don’t introduce coins tho)