EDIT: Or just do what Kry_s suggested xD
Can you tell us about your use case? If we can make some assumptions that might make it a lot easier.
E.g. are the Parts always axis-aligned boxes (AABs)? Or can they rotated, or be spheres/cylinders too?
To check if a AAB is fully within another AAB, you can do like this:
function isAABInsideAAB(position1, size1, position2, size2)
--Checks if an AABB defined by position1 and size1 is fully within the AABB defined by position2 and size2
-- if they have the same size and position, returns true.
local p1, p2 = position1, position2
local s1, s2 = size1/2, size2/2
local minX1, minX2 = p1.X - s1.X, p2.X - s2.X
local maxX1, maxX2 = p1.X + s1.X, p2.X + s2.X
local minY1, minY2 = p1.Y - s1.Y, p2.Y - s2.Y
local maxY1, maxY2 = p1.Y + s1.Y, p2.Y + s2.Y
local minZ1, minZ2 = p1.Z - s1.Z, p2.Z - s2.Z
local maxZ1, maxZ2 = p1.Z + s1.Z, p2.Z + s2.Z
return
(minX1 >= minX2 and maxX1 <= maxX2) and
(minY1 >= minY2 and maxY1 <= maxY2) and
(minZ1 >= minZ2 and maxZ1 <= maxZ2)
end
You can’t just use any part’s position and size for this. It’s important that the part is not e.g. rotated 90 degrees on an axis, so the rotation has to be (0, 0, 0). We can get around this with math, to convert any Part that’s only rotated in increments of 90 degrees to an AAB:
function partToAAB(part)
--Given an axis-aligned part, returns the position and size of an AAB that takes up the same space as the part,
-- but whose X, Y and Z axes are the same as the world's axes.
assert(isAxisAligned(part.CFrame), "Tried to convert a non-axis-aligned Part to an axis-alinged box.")
local AABPosition = part.Position
local AABSize = Vector3.new()
local worldCFrame = CFrame.new()
AABSize += part.CFrame:VectorToWorldSpace( Vector3.new(part.Size.X, 0, 0) )
AABSize += part.CFrame:VectorToWorldSpace( Vector3.new(0, part.Size.Y, 0) )
AABSize += part.CFrame:VectorToWorldSpace( Vector3.new(0, 0, part.Size.Z) )
return partPosition, AABSize
end
It errors if the part isn’t axis aligned, i.e. if it’s at an angle other than 90 degrees. That check looks like so:
function isAxisAligned(cFrame)
--Checks if a CFrame is rotated *only* at right angles.
local worldCFrame = CFrame.new()
--How much is the CFrame's sides facing towards the world's sides?
local dotFront = cFrame.XVector:Dot( worldCFrame.XVector )
local dotRight = cFrame.YVector:Dot( worldCFrame.YVector )
--Given any combination 90-degree rotations, the angles between the CFrame's sides and the world's sides can only
-- 0, 90 or 180 degrees. That corresponds to dot products of 1, 0, or -1. Any non-whole-number dot products % 1 will
-- equal somthing other than 0, while 1%1 = 0, 0%1 = 0 and -1%0 = 0.
-- so checking if these two dot products % 1 == 0 is sufficient to checking of the CFrame's sides are rotated only
-- through 90-degree increments, i.e. if the CFrame is axis-aligned
return dotFront % 1 == 0 and dotRight % 1 == 0
end
We can combine it all into a function that checks if one part is fully inside another:
function isPartInsidePart(part1, part2)
--Returns true if part1 is fully inside part2, assuming both are axis-aligned.
--Throws an error if part1 or part2 is not axis-aligned.
assert(isAxisAligned(part1.CFrame), "Tried to convert a non-axis-aligned Part to an axis-alinged box.")
assert(isAxisAligned(part2.CFrame), "Tried to convert a non-axis-aligned Part to an axis-alinged box.")
local AAB1Pos, AAB1Size = partToAAB(part1)
local AAB2Pos, AAB2Size = partToAAB(part1)
return isAABInsideAAB(aab1Pos, aab1Size, aab2Pos, aab2Size)
end
Of course, all this doesn’t work if you also need to check for parts that are rotated at arbitrary angles.