Camera:ViewportPointToRay(x,y,depth) Bug

Below you can see the script I have in a LocalScript. It basically just listens for clicks, creates a ray using Camera:ViewportPointToRay(mouse.X, mouse.Y, 1000), and then uses that ray to find the first hit. Simple, right? Well…No matter where I click, there is never a hit. It never works. The output always says "targ = nil hit = "…someVector3. Please look at the code and tell me what I’m doing wrong!!

local plr = game.Players.LocalPlayer
local cam = game.Workspace.CurrentCamera
local mouse = plr:GetMouse()

local UIS = game:GetService("UserInputService")

UIS.InputBegan:connect(function(input)
	if input.UserInputType == Enum.UserInputType.MouseButton1 then
		local ray = cam:ViewportPointToRay(mouse.X, mouse.Y, 1000)
		local targ,hit = game.Workspace:FindPartOnRay(ray, plr.Character)
		if targ then 
			local bcCache = targ.BrickColor
			targ.BrickColor = BrickColor.Random()
			delay(10,function() targ.BrickColor = bcCache end)
		end
		print("targ =",targ,"hit =",hit)
	end
end)

Seriously guys…This bug is a problem.

It’s the behaviour of the depth part of the method actually, not a bug. The ray’s direction is normalized, which is kinda annoying. The way depth actually seems to work is it moves the ray’s origin point along the lookvector of the camera’s CoordinateFrame, and if you run the following you’ll see that proves true (sadly).

local cam = workspace.CurrentCamera
local screenSize = cam.ViewportSize
local x, y = screenSize.X/2, screenSize.Y/2

local ray1 = cam:ViewportPointToRay(x, y, 0)
local ray2 = cam:ViewportPointToRay(x, y, 10)

local difference = ray1.Origin - ray2.Origin

print(difference.magnitude)
print(ray1.Direction.magnitude)
print(ray2.Direction.magnitude)

-->> 10
-->> 0.99999994039536
-->> 0.99999994039536

The only reason I actually came across this was for the same reason you did, trying to set the ray’s direction magnitude. The easiest way to work around is to just reconstruct the ray with the same origin and direction, but just change the direction magnitude. It would be really nice if it actually worked like that as I have no clue where shifting the origin and only having a unit direction vector is ever useful.

1 Like

Thank you! I’ll try your idea out now. Glad to know it wasn’t just me.

Okay.

There is apparently a problem with raycasting locally? Because no matter how I point my screen with the following code, targ is always nil.

		local ray = Ray.new(cam.CoordinateFrame.p, cam.CoordinateFrame.lookVector)
		targ,hit = game.Workspace:FindPartOnRay(ray, plr.Character)
		hit = CFrame.new(hit)

[quote] Okay.

There is apparently a problem with raycasting locally? Because no matter how I point my screen with the following code, targ is always nil.

local ray = Ray.new(cam.CoordinateFrame.p, cam.CoordinateFrame.lookVector) targ,hit = game.Workspace:FindPartOnRay(ray, plr.Character) hit = CFrame.new(hit) [/quote]

local distance = 999

local ray = Ray.new(cam.CoordinateFrame.p, cam.CoordinateFrame.lookVector * distance)
targ,hit = game.Workspace:FindPartOnRay(ray, plr.Character)
hit = CFrame.new(hit)

You have to multiply the direction vector with distance

[quote]

local distance = 999

local ray = Ray.new(cam.CoordinateFrame.p, cam.CoordinateFrame.lookVector * distance)
targ,hit = game.Workspace:FindPartOnRay(ray, plr.Character)
hit = CFrame.new(hit)

You have to multiply the direction vector with distance [/quote]

The wiki says to send a direction 0.o okay, I’ll try that.

1 Like