ScreenPointToRay help

Hi guys,

So I’m a little confused on what Camera:ScreenPointToRay() does. I thought it would essentially take a pixel and lock a ray onto that pixel, hitting whatever object that pixel was showing, allowing you to find the CFrame of that pixel. Here’s a picture of what I thought was happening:

It wasn’t working in my scenario, so I must’ve done something wrong or the function works differently than expected. Here’s my code that works as intended:

wait()

local mouse = game.Players.LocalPlayer:GetMouse()

local CurrentCam = game.Workspace.CurrentCamera

local VPSize = CurrentCam.ViewportSize

while true do

wait(1)

local NewRay = Ray.new(game.Workspace.CurrentCamera.CFrame.Position, CurrentCam.CFrame.LookVector.Unit*5000)--CurrentCam:ScreenPointToRay(0.5*VPSize.X, 0.5*VPSize.Y)

local Part = Instance.new("Part")

local Target, HitPos = workspace:FindPartOnRayWithIgnoreList(NewRay, {game.Players.LocalPlayer.Character})

if Target then

print(Target:GetFullName())

else

print("Did not hit anything.")

end

Part.Position = HitPos

print (Part.Position)

Part.Parent = workspace

Part.Anchored = true

Part.Size = Vector3.new(1,1,1)

Part.BrickColor = BrickColor.new("Bright red")

end

And here is my code using ScreenPointToRay:

wait()
local mouse = game.Players.LocalPlayer:GetMouse()

local CurrentCam = game.Workspace.CurrentCamera
local VPSize = CurrentCam.ViewportSize





while true do
	wait(1)
	
	local NewRay = CurrentCam:ScreenPointToRay(0.5*VPSize.X, 0.5*VPSize.Y)
	
	local Part = Instance.new("Part")
	local Target, HitPos = workspace:FindPartOnRayWithIgnoreList(NewRay, {game.Players.LocalPlayer.Character})
	if Target then
		print(Target:GetFullName())
	else
		print("Did not hit anything.")
	end
	Part.Position = HitPos
	print (Part.Position)
	Part.Parent = workspace
	Part.Anchored = true
	Part.Size = Vector3.new(1,1,1)
	Part.BrickColor = BrickColor.new("Bright red")
end

Any ideas on what I did wrong? Thanks!

4 Likes

What you want to do is create a new ray object, using the position and direction from the ScreenPointToRay.

local screenRay = CurrentCam:ScreenPointToRay(0.5*VPSize.X, 0.5*VPSize.Y)
local rayLength = 500
local newRay = Ray.new(screenRay.Origin, screenRay.Direction*rayLength)

This way you can give the ray a desired length, instead of a length of 1 stud.

9 Likes

Hey bigcrazycarboy,

I think I can help you.

This is what I tried for myself when I did something similar. ScreenPointToRay has a third argument which applies depth. Just change your NewRay to have a third argument like

local NewRay = CurrentCam:ScreenPointToRay(0.5*VPSize.X, 0.5*VPSize.Y, 10)

Just tested this myself and it works. Hope this helps!

EDIT: Read further down to what Coeptus posted before using this. It is still very helpful but probably not what you’re looking for exactly.

I was a bit late lol but this obviously works as well and this is the method I use in my game.

image

That is strange - even when I change the length of the ray to 5000 it still says it doesn’t hit anything. Not only that, but no matter how I move my camera, the coordinates of the hit CFrame stay the same (567, -2599, -4216)

For future readers, that’s somewhat misleading. The depth argument only offsets the origin of the created ray from the camera. The length is always 1 stud.

4 Likes

Yeah, Coeptus is right. When I said “this is the method I use in my game” I was referring to what Stickmasterluke posted. Definitely use what he posted. Thanks for clarifying what I missed!

2 Likes