Unexpected ClosestPoint() Method Behavior

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?
2 Likes

The answer was to change the argument of the :ClosestPoint() method from Vector3.new(dragPart.CFrame)) to dragPart.Position. I have one new question now: why?

Feel free to leave your answers before this closes.

vector3 doesn’t accept cframes by themselves as cframes contain both position and orientation.

some cool properties of cframes is that they contain a lookvector, upvector, and a rightvector.

1 Like

Ah. So dragPart.CFrame ended up giving me the numbers that weren’t the position? In that case, how does Vector3.new() determine which numbers to take? I don’t believe it to be the first 3, since running print(dragPart.CFrame) reveals that those numbers are the same as the position. I’m also confused as to why the part doesn’t just stay still, since all the other numbers stayed the same no matter how much I move the cube. Heck, I’m not even sure that the print statement is showing what the Vector3.new() statement is showing. Any ideas?

Vector3 are just xyz values. You can apply those xyz values to either position or orientation.

I don’t have any idea as of yet to why the part doesn’t stay still.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.