How to detect if a part is completely within another part?

I want to see if a part is completely inside of another, larger part. It’s worth noting that this will be done on renderstepped, so it would have to be performant.

1 Like

Use workspace:GetPartsInPart(). You can also do BasePart:GetTouchingParts()

The problem with these solutions is that the parts don’t need to be completely inside each other.

Yeah, I might just bite the bullet and get the Vector3 position of each corner and face of a part :​(

This might help:
How would i detect if a item/part is on a plot? - Help and Feedback / Scripting Support - DevForum | Roblox

The method linked bellow is mine and would work very quickly as it does simple math to tell if it in the part or not. Note this doesn’t work on angled stuff though.

Your method includes no link.


Why are you doing this in the first place?

I want to detect if a union (of any shape, size, and orientation) is completely within a player’s building plot

That’s my issue. The part can be at any angle/size

You should view the topic I linked. They have a solution.

“Assuming no rotation” is the first thing that they say in that topic.

Okay. In that case, GetTouchingParts will be your best bet.

Oh yeah, maybe I could have another part on the outside of the plot that is invisible and completely envelops it, and if a part is touching that boundary then I can determine that it’s not completely inside the box.

Perhaps check if the magnitude of the two parts is less than the smaller part’s longest side divided by 2?

Edit: this is wrong, and would likely be hard to calculate because of face issues, my bad

This felt like a bit of a challenge, so I decided to write this myself. Here’s my solution that I believe works:

local function doesPartEngulfOtherPart(bigPart: Part, smallPart: Part): boolean
	local bigPartBoundingBox = {
		first = bigPart.Position 
			+ bigPart.CFrame.XVector * bigPart.Size.X / 2 
			+ bigPart.CFrame.YVector * bigPart.Size.Y / 2 
			+ bigPart.CFrame.ZVector * bigPart.Size.Z / 2,
		
		second = bigPart.Position 
			- bigPart.CFrame.XVector * bigPart.Size.X / 2 
			- bigPart.CFrame.YVector * bigPart.Size.Y / 2 
			- bigPart.CFrame.ZVector * bigPart.Size.Z / 2,
	}
	
	local smallPartBoundingBox = {
		first = smallPart.Position 
			+ smallPart.CFrame.XVector * smallPart.Size.X / 2 
			+ smallPart.CFrame.YVector * smallPart.Size.Y / 2 
			+ smallPart.CFrame.ZVector * smallPart.Size.Z / 2,

		second = smallPart.Position 
			- smallPart.CFrame.XVector * smallPart.Size.X / 2 
			- smallPart.CFrame.YVector * smallPart.Size.Y / 2 
			- smallPart.CFrame.ZVector * smallPart.Size.Z / 2,
	}
	
	return
		bigPartBoundingBox.first.X > smallPartBoundingBox.first.X
		and bigPartBoundingBox.first.Y > smallPartBoundingBox.first.Y
		and bigPartBoundingBox.first.Z > smallPartBoundingBox.first.Z
		and bigPartBoundingBox.second.X < smallPartBoundingBox.second.X
		and bigPartBoundingBox.second.Y < smallPartBoundingBox.second.Y
		and bigPartBoundingBox.second.Z < smallPartBoundingBox.second.Z
	
end

It’s a little long to parse, but basically you get the top right (all positive) and bottom left (all negative) positions using the Unit Vectors to accommodate for any rotation in the parts. Then, it’s as simple as checking if the +XYZ of the smaller part is less than the +XYZ of the larger part, and -XYZ is greater than the larger part’s -XYZ. Please ask if you’re confused because I would like you to know how this works as well lol, not the biggest fan of just pasting code with no explanation

Edit: This works if the smaller part is rotated, but appears to not for the larger part. I’ll try my best to debug the issue.

1 Like

Nevermind, looks like this only works on one axis, but it could be changed a little bit to work on all of them using absolute values iirc

1 Like

Thank you so much. I haven’t been able to test this function yet but I’m sure it works. Also, in my game it’s the smaller part that rotates, not the larger one.

Wait, did you comment this before or after the edit on your main comment?

After, pretty sure the fix is just math.abs() on all of the values and then do a greater than check but I’m not entirely sure my math kinda sucks

or it just works try it

1 Like

Tested it and it works perfectly regardless of orientation! You’ve saved me a lot of “local faceFront = part.Position.X + (part.Size.X / 2)”.

1 Like

Wait, nvm. Just finished implementing it only to realize that it doesn’t completely work. Sometimes it works on the corners of the part, sometimes it doesn’t. It seems to have problems with the -Z direction

1 Like