How to get accurate mouse position?

How can you accurately get the mouse’s position without using Mouse.Hit?

function fire()
    local range = currentStats:GetAttribute("Range")
    
    local origin = muzzle.WorldPosition
    local mouseLocation = UserInputService:GetMouseLocation()
    local ray = currentCamera:ViewportPointToRay(mouseLocation.X, mouseLocation.Y)
    
    castBehavior.MaxDistance = range
    caster:Fire(origin, ray.Direction * range, currentStats:GetAttribute("Velocity"), castBehavior)
end

I’ve tried :ViewportPointToRay() and :ScreenPointToRay() and neither have brought me any good results


In the image above, you can see there’s a slight offset.

1 Like

Here you are creating two different rays: one is the viewportpointtoray, which is an unit ray originated at the camera’s position and that has a direction pointing to the 3D location your mouse is poining at. The second ray you fire from the muzzle’s position and has the same direction as the first ray. If you want to create a ray from the muzzle to the position you raycasted your mousr, you should do workspace:raycast(muzzle position, mouse raycast result. Position)

1 Like
    local range = currentStats:GetAttribute("Range")
    
    local mouseLocation = UserInputService:GetMouseLocation()
    local ray = currentCamera:ViewportPointToRay(mouseLocation.X, mouseLocation.Y)
    
    castBehavior.MaxDistance = range
    caster:Fire(ray.Origin, ray.Direction * range, currentStats:GetAttribute("Velocity"), castBehavior)
end

I got it to work but now I have to raycast from the camera position instead of my gun…

Now if you want to raycast from the gun ( to check if the bullet hit a wall, etc.) you make a second raycast using the raycast result: store the mouseCast in a variable and do

if mouseCast then
local gunCast = workspace:raycast(mullet.origin, mouseCast.Position)
End

1 Like

You should subtract the GUI inset from the mouse location before feeding it to ViewportPointToRay():

local UserInputService = game:GetService("UserInputService")
local currentCamera = workspace.CurrentCamera

function fire()
    local range = currentStats:GetAttribute("Range")
    local origin = muzzle.WorldPosition

    local mouseLocation = UserInputService:GetMouseLocation()
    local guiInset = UserInputService:GetGuiInset()  -- This is the key!
    local viewportPoint = Vector2.new(
        mouseLocation.X,
        mouseLocation.Y - guiInset.Y
    )

    local ray = currentCamera:ViewportPointToRay(viewportPoint.X, viewportPoint.Y)

    castBehavior.MaxDistance = range
    caster:Fire(origin, ray.Direction * range, currentStats:GetAttribute("Velocity"), castBehavior)
end

I tried this but it ends up being completely off when I visualize the raycast.

local range = currentStats:GetAttribute("Range")
    
    local mouseLocation = UserInputService:GetMouseLocation()
    local guiInset = GuiService:GetGuiInset()
    local ray = currentCamera:ViewportPointToRay(mouseLocation.X, mouseLocation.Y)
    local mouseRaycast = Workspace:Raycast(ray.Origin, ray.Direction * range, raycastParams)
    
    if mouseRaycast then
        castBehavior.MaxDistance = range
        caster:Fire(muzzle.WorldPosition, mouseRaycast.Position, currentStats:GetAttribute("Velocity"), castBehavior)
    end

Fixed, I have to use (mouseRaycast.Position - muzzle.WorldPosition).Unit for the direction instead of just mouseRaycast.Position

I also made it so the mouseRaycast doesnt have to hit anymore. Rather i just add origin and direction so even if it doesnt hit itll still work

    
    local mouseLocation = UserInputService:GetMouseLocation()
    local ray = currentCamera:ViewportPointToRay(mouseLocation.X, mouseLocation.Y)
    local mouseRaycast = Workspace:Raycast(ray.Origin, ray.Direction * range, raycastParams)
    local mouseIntersection = mouseRaycast and mouseRaycast.Position or ray.Origin + (ray.Direction * range)
    
    castBehavior.MaxDistance = range
    caster:Fire(muzzle.WorldPosition, (mouseIntersection - muzzle.WorldPosition).Unit, currentStats:GetAttribute("Velocity"), castBehavior)
1 Like