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?
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
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.
-- 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