I’m trying to get the closest point to a ray via the :ClosestPoint()
method. However, it has some unexpected behavior. I’ve tried to figure it out by creating some ball-shaped parts of different colors:
- Red is for the point used as the
:ClosestPoint()
argument - Green is for the ray’s origin
- Lighter, more transparent green is for the ray’s direction
- Blue is for the returned value of the
:ClosestPoint()
method
When I direct the ray towards a point, it ends up overshooting, no matter what angle I click on it from. It also ends up undershooting if I put the camera right up next to the point. It becomes somewhat aligned when I get further away, but players in the game I intend to use this for aren’t going to be able to get that far away anyway.
Behavior becomes increasingly less predictable when I get further away from the world’s origin. When I start dragging away from the world origin, the point snaps onto the ray’s origin. When I drag towards the world origin, the point gets further away. The point also gets even further away when I aim towards the world center.
I suspect it has something to do with the logic of my script that are currently controlling where these points land, but I have yet to find that part yet. Here’s a transcluded version:
local UserInputService = game:GetService("UserInputService")
local RunService = game:GetService("RunService")
local ray = nil
local raycast = nil
local dragPart = nil
local isDragging = false
-- Constructed reference points here
RunService.RenderStepped:Connect(function(deltaTime)
--[[ Update mouse ray ]]
local mouseLocation = UserInputService:GetMouseLocation()
ray = workspace.CurrentCamera:ViewportPointToRay(mouseLocation.X, mouseLocation.Y)
end)
-- Set the raycast variable here whenever the mouse moves
UserInputService.InputBegan:Connect(function(input, gameProcessedEvent)
--[[ Start dragging part ]]
if input.UserInputType == Enum.UserInputType.MouseButton1 and
raycast
then
isDragging = true
dragPart = raycast.Instance
while isDragging do
local unitRay = ray.Unit
local closestPoint = unitRay:ClosestPoint(Vector3.new(dragPart.CFrame))
-- rayOriRefPart, rayDirRefPart, and nearPtRefPart are the green, light green, and blue balls respectively
rayOriRefPart:PivotTo(CFrame.new(unitRay.Origin))
rayDirRefPart:PivotTo(CFrame.new(unitRay.Direction) * CFrame.new(unitRay.Origin))
nearPtRefPart:PivotTo(CFrame.new(closestPoint))
task.wait()
end
end
end)
UserInputService.InputEnded:Connect(function(input, gameProcessedEvent)
--[[ Stop dragging part ]]
if input.UserInputType == Enum.UserInputType.MouseButton1 then
isDragging = false
dragPart = nil
end
end)
All in all, this behavior has spawned the following questions I’d like answered:
- When the ray is aimed at the point, shouldn’t the closest point be the point itself?
- Why is it that the point gets further away the more I point it to the world’s center, but acts more reasonably when I point it away?
- Why does this effect get exacerbated when I get further away from the center?