I’m trying to calculate the distance between 2 parts, but I don’t want to use their position, it’s hard to get what I mean so I drew something:
I would like to calculate the purple line, is there any way I can do that?
I’m trying to calculate the distance between 2 parts, but I don’t want to use their position, it’s hard to get what I mean so I drew something:
You could try something like this, takes the position and clamps to the part 2, i think this is a right function, though raycasting might work
local function getClosestDistance(part1, part2)
-- Get closest point on part2's surface from part1's center
local closestPoint = part2.CFrame:PointToObjectSpace(part1.Position)
local halfSize = part2.Size / 2
-- Clamp to part2's bounds
closestPoint = Vector3.new(
math.clamp(closestPoint.X, -halfSize.X, halfSize.X),
math.clamp(closestPoint.Y, -halfSize.Y, halfSize.Y),
math.clamp(closestPoint.Z, -halfSize.Z, halfSize.Z)
)
-- Convert back to world space
closestPoint = part2.CFrame:PointToWorldSpace(closestPoint)
-- Distance from part1's closest surface point to that point
local part1Closest = part1.CFrame:PointToObjectSpace(closestPoint)
local part1HalfSize = part1.Size / 2
part1Closest = Vector3.new(
math.clamp(part1Closest.X, -part1HalfSize.X, part1HalfSize.X),
math.clamp(part1Closest.Y, -part1HalfSize.Y, part1HalfSize.Y),
math.clamp(part1Closest.Z, -part1HalfSize.Z, part1HalfSize.Z)
)
part1Closest = part1.CFrame:PointToWorldSpace(part1Closest)
return (part1Closest - closestPoint).Magnitude
end
i just made a simple example for you. this is how i would get the distance between corners. (this example is very simple. u should use a loop to calculate all corners if that is ur intention)
code:
local Part1 = workspace.Part1
local Part2 = workspace.Part2
local function getHalfSize(part)
return part.Size.X / 2, part.Size.Y / 2, part.Size.Z / 2
end
local HalfX1, HalfY1, HalfZ1 = getHalfSize(Part1)
local HalfX2, HalfY2, HalfZ2 = getHalfSize(Part2)
local PartCorner1 = Part1.CFrame * CFrame.new(HalfX1, HalfY1, HalfZ1)
local PartCorner2 = Part2.CFrame * CFrame.new(-HalfX2, HalfY2, HalfZ2)
local Corners = {
PartCorner1.Position,
PartCorner2.Position
}
local cornerDistance = (Corners[1] - Corners[2]).Magnitude
for _, corner in ipairs(Corners) do
local referencePart = Instance.new("Part")
referencePart.Anchored = true
referencePart.BrickColor = BrickColor.random()
referencePart.Transparency = 0.5
referencePart.Size = Vector3.new(1, 1, 1)
referencePart.Position = corner
referencePart.Parent = workspace
end
print("Distance between corners: " .. cornerDistance)
place file:
DistanceBetweenCorners.rbxl (74.4 KB)
Also have a script for getting corners, but I think my earilier one is better because it covers edges, this one just gets every corner/vertice and compares.
local function getVertices(part)
local cf = part.CFrame
local size = part.Size / 2
return {
cf:PointToWorldSpace(Vector3.new(-size.X, -size.Y, -size.Z)),
cf:PointToWorldSpace(Vector3.new(-size.X, -size.Y, size.Z)),
cf:PointToWorldSpace(Vector3.new(-size.X, size.Y, -size.Z)),
cf:PointToWorldSpace(Vector3.new(-size.X, size.Y, size.Z)),
cf:PointToWorldSpace(Vector3.new( size.X, -size.Y, -size.Z)),
cf:PointToWorldSpace(Vector3.new( size.X, -size.Y, size.Z)),
cf:PointToWorldSpace(Vector3.new( size.X, size.Y, -size.Z)),
cf:PointToWorldSpace(Vector3.new( size.X, size.Y, size.Z)),
}
end
local function closestPointOnPart(point, part)
local localPoint = part.CFrame:PointToObjectSpace(point)
local halfSize = part.Size / 2
localPoint = Vector3.new(
math.clamp(localPoint.X, -halfSize.X, halfSize.X),
math.clamp(localPoint.Y, -halfSize.Y, halfSize.Y),
math.clamp(localPoint.Z, -halfSize.Z, halfSize.Z)
)
return part.CFrame:PointToWorldSpace(localPoint)
end
local function getMinDistanceBetweenParts(part1, part2)
local vertices1 = getVertices(part1)
local vertices2 = getVertices(part2)
local minDistance = math.huge
-- Check each vertex of part1 to closest point on part2
for _, vertex in ipairs(vertices1) do
local closest = closestPointOnPart(vertex, part2)
local distance = (vertex - closest).Magnitude
minDistance = math.min(minDistance, distance)
end
-- Check each vertex of part2 to closest point on part1
for _, vertex in ipairs(vertices2) do
local closest = closestPointOnPart(vertex, part1)
local distance = (vertex - closest).Magnitude
minDistance = math.min(minDistance, distance)
end
return minDistance
end
Pretty hard to beat that one without going all direct.
function getMinDistanceBetweenParts(p1,p2)
local cf1,s1=p1.CFrame,p1.Size*0.5
local cf2,s2=p2.CFrame,p2.Size*0.5
local v1={
Vector3.new(-s1.X,-s1.Y,-s1.Z),Vector3.new(-s1.X,-s1.Y,s1.Z),
Vector3.new(-s1.X,s1.Y,-s1.Z),Vector3.new(-s1.X,s1.Y,s1.Z),
Vector3.new(s1.X,-s1.Y,-s1.Z),Vector3.new(s1.X,-s1.Y,s1.Z),
Vector3.new(s1.X,s1.Y,-s1.Z),Vector3.new(s1.X,s1.Y,s1.Z)
}
local v2={
Vector3.new(-s2.X,-s2.Y,-s2.Z),Vector3.new(-s2.X,-s2.Y,s2.Z),
Vector3.new(-s2.X,s2.Y,-s2.Z),Vector3.new(-s2.X,s2.Y,s2.Z),
Vector3.new(s2.X,-s2.Y,-s2.Z),Vector3.new(s2.X,-s2.Y,s2.Z),
Vector3.new(s2.X,s2.Y,-s2.Z),Vector3.new(s2.X,s2.Y,s2.Z)
}
local min=math.huge
for i=1,8 do
local w1=cf1:PointToWorldSpace(v1[i])
local l2=cf2:PointToObjectSpace(w1)
l2=Vector3.new(math.clamp(l2.X,-s2.X,s2.X),math.clamp(l2.Y,
-s2.Y,s2.Y),math.clamp(l2.Z,-s2.Z,s2.Z))
local c2=cf2:PointToWorldSpace(l2)
min=math.min(min,(w1-c2).Magnitude)
end
for i=1,8 do
local w2=cf2:PointToWorldSpace(v2[i])
local l1=cf1:PointToObjectSpace(w2)
l1=Vector3.new(math.clamp(l1.X,-s1.X,s1.X),math.clamp(l1.Y,
-s1.Y,s1.Y),math.clamp(l1.Z,-s1.Z,s1.Z))
local c1=cf1:PointToWorldSpace(l1)
min=math.min(min,(w2-c1).Magnitude)
end
return min
end
Bam take this:
local function getClosestDistanceOptimized(part1, part2)
local function closestPointOnPart(point, part)
local localPoint = part.CFrame:PointToObjectSpace(point)
local halfSize = part.Size / 2
localPoint = Vector3.new(
math.clamp(localPoint.X, -halfSize.X, halfSize.X),
math.clamp(localPoint.Y, -halfSize.Y, halfSize.Y),
math.clamp(localPoint.Z, -halfSize.Z, halfSize.Z)
)
return part.CFrame:PointToWorldSpace(localPoint)
end
local function getVertices(part)
local cf = part.CFrame
local size = part.Size / 2
return {
cf:PointToWorldSpace(Vector3.new(-size.X, -size.Y, -size.Z)),
cf:PointToWorldSpace(Vector3.new(-size.X, -size.Y, size.Z)),
cf:PointToWorldSpace(Vector3.new(-size.X, size.Y, -size.Z)),
cf:PointToWorldSpace(Vector3.new(-size.X, size.Y, size.Z)),
cf:PointToWorldSpace(Vector3.new( size.X, -size.Y, -size.Z)),
cf:PointToWorldSpace(Vector3.new( size.X, -size.Y, size.Z)),
cf:PointToWorldSpace(Vector3.new( size.X, size.Y, -size.Z)),
cf:PointToWorldSpace(Vector3.new( size.X, size.Y, size.Z)),
}
end
-- Quick check: if parts are far apart, use center approximation
local centerDist = (part1.Position - part2.Position).Magnitude
local maxDiagonal = (part1.Size.Magnitude + part2.Size.Magnitude) / 2
if centerDist > maxDiagonal * 2 then
-- Parts are far apart, use fast approximation
return math.max(0, centerDist - maxDiagonal)
end
-- Parts are close, use accurate calculation
local minDistance = math.huge
local vertices1 = getVertices(part1)
for _, vertex in ipairs(vertices1) do
local closestPoint = closestPointOnPart(vertex, part2)
local distance = (vertex - closestPoint).Magnitude
minDistance = math.min(minDistance, distance)
end
local vertices2 = getVertices(part2)
for _, vertex in ipairs(vertices2) do
local closestPoint = closestPointOnPart(vertex, part1)
local distance = (vertex - closestPoint).Magnitude
minDistance = math.min(minDistance, distance)
end
return minDistance
end
What about simply using
BasePart:GetClosestPointOnSurface(Vector3)
local function getDistance(p1: BasePart, p2: BasePart): number
local pos1 = p1:GetClosestPointOnSurface(p2.Position)
local pos2 = p2:GetClosestPointOnSurface(p1.Position)
return (pos2-pos1).Magnitude
end
game:GetService("RunService").Heartbeat:Connect(function()
print(getDistance(workspace.part1, workspace.part2))
end)
This is why I come here.. what a crazy way to do this. Used both.. genius.
Now I want to try again..
function getTrueClosestDistance(p1, p2, iterations)
iterations = iterations or 5
local pos1 = p1.Position
local pos2 = p2.Position
for i = 1, iterations do
pos1 = p1:GetClosestPointOnSurface(pos2)
pos2 = p2:GetClosestPointOnSurface(pos1)
end
return (pos2 - pos1).Magnitude
end
game:GetService("RunService").Heartbeat:Connect(function()
print(getTrueClosestDistance(workspace.part1, workspace.part2))
end)
Eh, who even uses scripts these days? You got go in style
local module = {}
function module.GetDistance(p1: BasePart, p2: BasePart): number
local pos1 = p1:GetClosestPointOnSurface(p2.Position)
local pos2 = p2:GetClosestPointOnSurface(p1.Position)
return (pos2-pos1).Magnitude
end
return module
Boom, Boom, Boom. It’s a module script.
I see you also changed up on the spot .. ![]()
This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.