I have been stuck on this for about the last hour and a half, and it is the only thing stopping me.
Basically I want to get the 3D world position from a point on the camera. I have tried ViewportPointToRay, and it has always ended up above the camera somehow?
This is my code:
local function NewPoint(point: CFrame)
local p = Instance.new("Attachment",Host)
p.WorldCFrame = point
p.Name = `{tostring(point.X)}, {tostring(point.Y)}, {tostring(point.Z)}`
p.Visible = true
end
local function GenerateGrid()
local CamRes = camera.ViewportSize
repeat
CamRes = camera.ViewportSize
task.wait()
until CamRes.X > 1 and CamRes.Y > 1
local squareSize = math.min(CamRes.X,CamRes.Y)/resolution
for x = 1, CamRes.X, squareSize do
for y = 1, CamRes.Y, squareSize do
local scaleX, scaleY = x / CamRes.X, y / CamRes.Y
local worldPos = camera:ViewportPointToRay(x, y).Origin
NewPoint(CFrame.new(worldPos))
end
end
end
have you tried ScreenPointToRay and make sure you are setting the direction and a long enough length that the ray hits something in the 3d space… by default viewportpointtoray is only 1 stud in length so if using it will also need to increase the length and make sure it hits something
this is also explained on the ViewportPointToRay hub info
I have tried ScreenPointToRay, and it does the same. It also would not work for what I need. I only need the origin of the ray, so I’m not sure I need to increase the ray length.
I have tested this with screenpoint and viewportpoint using origins and even some depth and it works fine… you can see it with this simple code and an anchored part in replicated storage set size to .1 and maybe color red… this code will select random spots on the screen to get origin of then spawns the parts for visual.
it seems it maybe working maybe because you have no depth they are very close together try adding some depth to the cast so it shift the origin out from the camera some
local camera = workspace.CurrentCamera
for i = 1 , 100 do
local x = math.random(1,camera.ViewportSize.X)
local y = math.random(1,camera.ViewportSize.Y)
local length = 1
local unitRay = camera:ViewportPointToRay(x, y,1) -- this will put it out just 1 stud from camera base so they are not put together in bunch right at camera..
--local unitRay = camera:ScreenPointToRay(x, y) -- no depth keep at origin
local extendedRay = Ray.new(unitRay.Origin, unitRay.Direction * length)
local part = game.ReplicatedStorage.Part:Clone()
part.Position = unitRay.Origin
--part.Position = extendedRay.Origin
part.Parent = workspace
task.wait(.1)
end
here is code like your using 5 and 10 depth on the viewportpoint or screenpoint (only difference is the 36 offset pixels with screenpoint)
task.wait(2)
local camera = workspace.CurrentCamera
local CamRes = camera.ViewportSize
local squareSize = math.min(CamRes.X,CamRes.Y)/50
print(squareSize)
for x = 1, CamRes.X, squareSize do
for y = 1, CamRes.Y, squareSize do
local scaleX, scaleY = x / CamRes.X, y / CamRes.Y
local worldPos = camera:ScreenPointToRay(x, y, 10).Origin
local p = Instance.new("Attachment",workspace.SpawnLocation)
p.WorldCFrame = CFrame.new(worldPos)
p.Name = 'test' --{tostring(worldPos.X)}, {tostring(worldPos.Y)}, {tostring(worldPos.Z)}
p.Visible = true
end
end
it producing attachment setups like this. first 2 are 5 res and i zoomed out to show
for x = 1, CamRes.X, squareSize do
for y = 1, CamRes.Y, squareSize do
local worldPos = camera:ScreenPointToRay(x, y, 10).Origin
NewPoint(CFrame.new(worldPos))
end
end