Where to raycast in a third person shooter

Hi developers,

I’ve been working on a third person gun framework, and i’ve run into an issue:

To shoot the gun, i send out a raycast in the direction of the camera and from the position with the camera. This means when you shoot the gun, it will shoot from the crosshair (at least in theory - it actually raycasts slightly above the crosshair, but i’ll get into that later). The thing is, this means it’s not really shooting from the gun, it’s shooting from the camera, so if something is blocking the camera you won’t be able to shoot anything, and if the camera is zoomed out the raycast will be traveling further.

(you can also see for yourself here):

-- this is essentially how i've been raycasting
workspace:Raycast(camera.CFrame.Position, camera.CFrame.LookVector.Unit * 300, ...)

So, my question is this: how can i raycast from the gun while still having the shot line up with the crosshair?

1 Like

Get a unit vector pointing at the crosshair

local direction = (Mouse.Hit.Position - Camera.CFrame.Position).Unit

and use it for the 2nd argument in workspace:RayCast()

1 Like

Thanks - this works, but how does it work? Also is there an alternative to using Mouse.Hit.Position in this context?

You can raycast from Character.Head.Position instead of from the Camera.

You can use Mouse.Hit.Position to get where the camera points, then from the gun raycast to the position.

Alright, i’ve gotten a bit closer to fixing this.

I modified that code to use a substitute for Mouse.Hit.Position, and it behaves in the same way.

local params = RaycastParams.new()
params.RespectCanCollide = true
					
local cameraHit = workspace:Raycast(camera.CFrame.Position, camera.CFrame.LookVector.Unit * 1000)
local shootDir = (cameraHit.Position or (camera.CFrame.Position + (camera.CFrame.LookVector.Unit * 1000)))

workspace:Raycast((shootDir - camera.CFrame.Position).Unit, gun.Position)

But it has some issues:

It shoots slightly above the crosshair for some reason

And every time you shoot it the next ray will be offset slightly

because the raycast is going on the parts you created or you arent even using the params

local bullets = {}

local params = RaycastParams.new()
params.FilterType = Enum.RaycastFilterType.Blacklist
params.FilterDescendantsInstances = bullets
params.RespectCanCollide = true

local cameraHit = workspace:Raycast(camera.CFrame.Position, camera.CFrame.LookVector.Unit * 1000, params)
local shootDir = (cameraHit.Position or (camera.CFrame.Position + (camera.CFrame.LookVector.Unit * 1000)))

workspace:Raycast((shootDir - camera.CFrame.Position).Unit, gun.Position, params)
1 Like

Oops, I forgot to use the RaycastParams :confused:

It doesn’t offset itself anymore, thanks!

For a third person shooter you should always raycast from the weapon to the mouse.

Though, a few posts down it appears to be a 2nd person (over the shoulder) shooter (correct me if I’m wrong).

You should raycast from the weapon to the mouse again, but since there’s a camera you should raycast from the center of the camera to the viewport instead of the mouse.

1 Like

It works by getting a vector at the camera.CFrame.Position pointing to the mouse.hit.position and converting it into a unit vector because why not. An alternative would be using the direction property from a ray returned from Camera:ViewportPointToRay()

Yep this is actually a game design problem hidden in a scripting problem.

Here are some examples of how other games dealt with the problem:

2 Likes

I enabled the mouse and saw that it was slightly above the crosshair, and it turns out it was because i hadn’t enabled ScreenGui.IgnoreGuiInset, so - after doing that - it works perfectly. Thanks for all your help everyone.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.