Positioning a part to go on top of another part, while respecting the cframe and size of each part

I’m trying to position a particular part to go on top of another part, while respecting the cframe and size of each part. So that instead of getting this:

I would get this:


Part1.CFrame = Part0.CFrame:ToWorldSpace(
	((CFrame.new(0, Part0.Size.Y/2+Part1.Size.Y/2, 0))*CFrame.Angles(0,0,math.rad(90))

Part0 being the plate, part1 being the cylinder

Why are you adding 90 degrees to the Part1’s z axis?
So that the cylinder is upright, as shown in the first photo, however it is levitating above Part0 (being the plate) because of this specifically Part1.Size.Y/2, which isn’t respecting how it is rotated

Try this to get the rotated part size:

local size = part.CFrame:VectorToWorldSpace(part.Size)

The issue is, that only supports parts with 90 degree angles, I would like to support any angle

Can you explain a little more about how exactly you want these positioned?

What are your inputs?

For example, do you want to say “place this cylinder so that it’s on this surface at this point”? Or do you have more info, like “place this cylinder so that it’s center is aligned with the rectangle and it’s in the +Y direction?

Hmm… This is a very intriguing problem.

I have linked a video of a demonstration I made of your problem. I hope I explained everything clearly and helped you with your issue.

Reply if you have any further questions.

Here is the code I used in the video:

function positionPartOnPart(part0, part1, orientation, direction)
	part1.CFrame = part0.CFrame
	part1.CFrame = part1.CFrame * orientation
	local magnitude = part1.Size.Magnitude/100
	local directionIncrement = (part0.CFrame:ToWorldSpace(CFrame.new(direction)).p - part1.CFrame.p).Unit * Vector3.new(magnitude, magnitude, magnitude)
	while isPartInPart(part0, part1) do
		part1.CFrame = part1.CFrame + directionIncrement

function isPartInPart(part0, part1)
	if table.find(workspace:GetPartsInPart(part0, OverlapParams.new()), part1) == nil then
		return false
	return true

positionPartOnPart(workspace["Part0"], workspace["Part1"], CFrame.Angles(math.rad(80),math.rad(50),math.rad(-245)), Vector3.new(0,1,0))

Demonstrated my problem perfectly! Loved your demonstration. I’ll look into make it more performant, perhaps by using raycasts. Seems quite expensive to use getpartsinpart, nevertheless good solution. Was too fixated on a solution that is entirely cframe that I overlooked that. :+1:

1 Like

Check the other reply on this post, it describes the problem. If you have any idea other than their solution, let me know, otherwise it’s fine, their solution will suffice.

Yeah, haha. I agree- it’s quite expensive, but I could not find another way to do this that wasn’t more inefficient. Good luck on your project! I’m sure you will find a way.

You have the size of a part - why not use it?

function updatePart1()
    -- The LookVector is where the front of the part is *relative to the part itself*.
    -- The LookVector has a magnitude (a length) of 1.
    -- We add half of the size of Part1 and Part0 to get the distance the parts should be apart.
    -- Finally, we multiply the distance by the LookVector and add it to the CFrame.
    Part1.CFrame = (Part0.CFrame + -- Add Part0 and the multiplied LooKVector
        (Part0.CFrame.LookVector * -- Multiply the LookVector by
                (Part0.Size.Z / 2) -- half of Part0's size
                (Part1.Size.X / 2) -- half of Part1's size (but on the X axis, because we rotated it)
        )) * CFrame.fromEulerAnglesXYZ(0, math.rad(90), 0) -- Rotate Part1

Here’s an example place.


Red is front, blue is left, green is top.

Press Shift+P in game for a free camera.


@xendatro’s iterative solution seems good enough to me. If you have performance problems later you can come back to it and try to find a closed-form solution.

If you constrain the problem to “project a rotated box onto a rotated plane” instead of “…onto another rotated box”, the problem is more straightforward.

Regardless I would mark @xendatro’s reply as the solution.