Finding the point on an object closest to the player

Lets say I have a player (Rig) and a part that could potentially be rotated and scaled in any possible way (grey part).

How could I find the the point on the object that is the closest to the player’s HumanoidRootPart position? This point shouldn’t be limited to just be on the corners or vertices, but rather anywhere along the surface.

Example (probably not accurate, just done by sight)
image

Do you want the part to be the “finder” or the player?

1 Like

local Part = workspace.Part

local GetCorners = function(Inst)	
	local Corners = {}
	
	local Pos = Inst.CFrame
	local Size = Inst.Size

	local frontFaceCenter = (Pos + Pos.LookVector * Size.Z/2)
	local backFaceCenter = (Pos - Pos.LookVector * Size.Z/2)
	local topFrontEdgeCenter = frontFaceCenter + frontFaceCenter.UpVector * Size.Y/2
	local bottomFrontEdgeCenter = frontFaceCenter - frontFaceCenter.UpVector * Size.Y/2
	local topBackEdgeCenter = backFaceCenter + backFaceCenter.UpVector * Size.Y/2
	local bottomBackEdgeCenter = backFaceCenter - backFaceCenter.UpVector * Size.Y/2
	
	Corners.topFrontRight = (topFrontEdgeCenter + topFrontEdgeCenter.RightVector * Size.X/2)
	Corners.topFrontLeft = (topFrontEdgeCenter - topFrontEdgeCenter.RightVector * Size.X/2)
	Corners.bottomFrontRight = (bottomFrontEdgeCenter + bottomFrontEdgeCenter.RightVector * Size.X/2)
	Corners.bottomFrontLeft = (bottomFrontEdgeCenter - bottomFrontEdgeCenter.RightVector * Size.X/2)
	Corners.topBackRight = (topBackEdgeCenter + topBackEdgeCenter.RightVector * Size.X/2)
	Corners.topBackLeft = (topBackEdgeCenter - topBackEdgeCenter.RightVector * Size.X/2)
	Corners.bottomBackRight = (bottomBackEdgeCenter + bottomBackEdgeCenter.RightVector * Size.X/2)
	Corners.bottomBackLeft = (bottomBackEdgeCenter - bottomBackEdgeCenter.RightVector * Size.X/2)

	return Corners
end

local GetClosestCorner = function(Inst, Corners)
	local ClosestCorner = nil 
	
	for i,v in pairs(Corners) do 
		local Magnitude = (Inst.Position - v.Position).Magnitude
		
		if (ClosestCorner == nil) then 
			ClosestCorner = v
		end
		
		if (Magnitude < (Inst.Position - ClosestCorner.Position).Magnitude) then 
			ClosestCorner = v
		end
	end
	
	return ClosestCorner
end

game:GetService("Players").PlayerAdded:Connect(function(Player)
	Player.CharacterAdded:Connect(function(Char)
		local Root = Char:WaitForChild("HumanoidRootPart")
		
		task.spawn(function()
			while true and task.wait() do 
				local Corners = GetCorners(Part)
				local ClosestCorner = GetClosestCorner(Root, Corners)
				
				for i,v in pairs(Part:GetChildren()) do 
					if (v.Name == "CORNER_VISUAL") then 
						v:Destroy()
					end
				end
				
				for i,v in pairs(Corners) do 
					local VisualPart = Instance.new("Part")
					VisualPart.Size = Vector3.new(1, 1, 1)
					VisualPart.Anchored = true 
					VisualPart.CanCollide = false
					VisualPart.Transparency = 0.5
					VisualPart.CFrame = v
					if (ClosestCorner == v) then 
						VisualPart.Color = Color3.fromRGB(0, 255, 0)
					else 
						VisualPart.Color = Color3.fromRGB(255, 0, 0)
					end
					
					VisualPart.Name = "CORNER_VISUAL"
					VisualPart.Parent = Part
				end
				
			end
		end)
	end)
end)

Got the GetCorners function from this topic: How to find corners of part? - #12 by debugger57

1 Like

Hello, thanks for the solution, but I was hoping to find a point anywhere along the surface of the part, not just limited to the corners.

Changed, I’m using this now, thanks!

Not sure if one is necessarily “better”, but I guess for intuitions sake most likely the player would act as the “finder”.

local Character = script.Parent
function Get(V:BasePart?)
	for _,d in workspace:GetChildren() do
		if d:IsA("BasePart") and d:GetAttribute("Figure") == true then
			if (d.Position - V.Position).Magnitude <= 7 then
				return true,d
			else
				return false,d
			end
		end
	end
end
function Create(State:boolean?,Part:BasePart?,v)
	if State then
		if not Part:FindFirstChild("LookATT") then
			local ATT = Instance.new("Attachment")
			ATT.Visible = true
			ATT.Position = Part.CFrame:ToObjectSpace(v.CFrame).LookVector
			ATT.Name = "LookATT"
			ATT.Parent = Part
		end
	else
		pcall(function()
			Part:FindFirstChild(
				"LookATT"
			):Destroy()
		end)
	end
end
task.spawn(function()
	while true do
		task.wait()
		for _,v in Character:GetChildren() do
			if v:IsA("BasePart") then
				local bool,Inst = Get(v)
				print(bool,Inst)
				Create(bool,Inst,v)
			end
		end
	end
end)

Are you looking for something similar to this? Figure attribute is used as a whitelist so objects like baseplate dont account for the loop.

My approach for this is probably using raycast. When using raycast, store all valid raycast results in a table and compare the magnitude between whatever position you are comparing to the part you are checking. Be sure the whitelist parameter is only that specific part or the collision of the raycast may hit something else returning a false result. More raycast = more accuracy.

Thanks for all the suggestions, but for now I think I’ll just go for the corner detection as I think I can simply my idea to allow for that instead.

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