Hmm, so this is a tricky one.
We can’t use mouse.Hit
for the reasons you have discussed and we can’t use the 2D space either b/c then we have issues with our camera’s pitch causing issues.
The way I’d approach this is with a plane intersection. E.g. finding where a ray intersects with an infinite surface.
We can define a plane with a point on the plane and the surface normal of the plane. In your case the point will be arrow.Position
and the normal will be Vector3.new(0, 1, 0)
.
As for the ray we need the same information we’d need for a raycast (a starting position and a direction). Luckily the camera has a method that will provide that for us via :ScreenPointToRay(x, y, depth)
.
Now onto the math:
Pardon my poor writing/drawing
Ray Point = rp
Ray Direction = rd
Plane Point = pp
Plane Normal = pn
We have two equations we will work with
Intersection = rp + rd * some_scalar
(Intersection - pp):Dot(pn) = 0
Now we plug the first into the second and solve for some_scalar
(rp + rd * some_scalar - pp):Dot(pn) = 0
rp:Dot(pn) + rd:Dot(pn) * some_scalar - pp:Dot(pn) = 0
some_scalar = (pp - rp):Dot(pn) / rd:Dot(pn)
So then our function would be:
local function planeRay(rp, rd, pp, pn)
local scalar = (pp - rp):Dot(pn) / rd:Dot(pn)
return rp + rd * scalar
end
-- your code might then be:
local unitRay = game.Workspace.CurrentCamera:ScreenPointToRay(mouse.X, mouse.Y)
local intersection = planeRay(unitRay.Origin, unitRay.Direction, arrow.Position, Vector3.new(0, 1, 0))
Now some things to take note of, when rd and pn are orthogonal this function will give a nan vector because the ray direction runs across the surface of the plane which either means infinite intersections or none at all. Just something to keep in mind…
Hope that helps!
Edit: Here’s a quick place file in action.
planeray.rbxl (17.9 KB)
Edit 2: I suppose I should mention from a math standpoint we are making use of the fact that the dot product is equivalent to a:Dot(b) = a.Magnitude * b.Magnitude * cos(shortest_angle_between_a_and_b)
. As such since cos(90 degrees) = 0
we can use the dot product to make one of our equations.