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:
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
end
end
function isPartInPart(part0, part1)
if table.find(workspace:GetPartsInPart(part0, OverlapParams.new()), part1) == nil then
return false
end
return true
end
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.
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.
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
end
@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.