Closest Part Question

Hey all,
I am trying to make a system that gets the closest part. Anyone have any good ideas for checking which part the player is looking at*? For example, if I have two parts each stacked up on each other, I want to detect the one the player is directly looking at.

*Looking for more methods

Code thus far:

spawn(function()
	while task.wait(0.25) do
		if not on then
			local extents = 3 * Vector3.one
			local region = Region3.new(rootPart.Position - extents, rootPart.Position + extents)
			local closest_parts = workspace:FindPartsInRegion3WithWhiteList(region,{workspace.Interchange})
			for i = 1, #closest_parts do
				
			end
		end
	end
end)
2 Likes

Could you use a raycast where the player is looking, or are you trying to do something different?

2 Likes

you could use magnitude in order to get this distance

3 Likes

Yes but they want to see which part the player is looking at if the magnitude is the same (two parts stacked on each other), I suggest using a raycast from the player’s head or HumanoidRootPart the choice is yours.

3 Likes

If you only want to check which part the player is looking at, you could use the player’s mouse to do so. For example, the code below prints out a part that the player is looking at every time the mouse moves.

local players = game:GetService("Players")

local mouse = players.LocalPlayer:GetMouse()

mouse.Move:Connect(function()
	print(mouse.Target)
end)
5 Likes

no i am trying to get it so that if a player walks up to a part something will appear. However, if parts are stacked up on top of each other, I want it so that I can identify which one the player is “closer” to (i.e pointing to)

2 Likes

this is probably the best way (what I was thinking) - raycasting seems to serve as the only possibility here.

3 Likes

For all the parts, extract their viewport position via Camera:WorldToViewportPoint.
Then from there getting the closest point to the mouse is straightforward

local lp = game:GetService('Players').LocalPlayer
local uis = game:GetService('UserInputService')

local boxSize: Vector3 = Vector3.new(10, 10, 10)
local checkOLP: OverlapParams = OverlapParams.new() do
	checkOLP.FilterDescendantsInstances = {workspace:WaitForChild('Parts')}
	checkOLP.FilterType = Enum.RaycastFilterType.Include
end

local highlight = Instance.new('Highlight') do
	highlight.DepthMode = Enum.HighlightDepthMode.AlwaysOnTop
	highlight.Parent = game
end

uis.InputBegan:Connect(function(k: InputObject, gp: boolean)
	if gp then return end
	if k.UserInputType ~= Enum.UserInputType.MouseButton1 then return end
	
	local char = lp.Character
	if not char then return end
	local hrp: BasePart = char:WaitForChild('HumanoidRootPart')
	
	local cam = workspace.CurrentCamera
	local mPos: Vector2 = uis:GetMouseLocation()
	local mPos: Vector3 = Vector3.new(mPos.X, mPos.Y, 0) --convert to Vector3 for faster math (Vector3 is a native type)
	local parts: {BasePart} = workspace:GetPartBoundsInBox(hrp.CFrame, boxSize, checkOLP)	
	local closest: BasePart?, limit: number = parts[1], math.huge
	print(#parts)
	
	for _, p in parts do
		local pos: Vector3, visible: boolean = cam:WorldToViewportPoint(p.Position)
		if visible then
			local dist: number = (mPos - pos).Magnitude
			if dist < limit then
				limit = dist
				closest = p
			end
		end
	end
	
	highlight.Adornee = closest
end)
1 Like

I like this idea very much! Thank you!

1 Like

This seems like the most viable option. Thank you so much for your assistance!

(going to mark you as a solution so others can benefit!)

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