How would I keep a part upright using CFrame?

Hello there. I will try to make this as short as possible. I have a part which is welded to a model. The model that is welded to can rotate around the Y-axis and can tilt upwards and downwards (I would say the X-axis, but in a 3D space, the Z-axis might be affected too). Having that in mind, I want the part which is welded to the model to rotate around the Y-axis along with the model, but I want to restrict the tilting motion. To reword, the part should move with the model like any other welded part would, but it’s tilting should be locked, so if for instance the front surface of the model was to be tilting and facing towards the sun, the part should be rotated to the direction of the sun, but not tilting to look up towards it. Here is an example (look at the seating module and how it is not tilting along with the crane):

Although I was able to achieve this effect with constraints and making the base of the platform very heavy, I do not trust Roblox physics enough to handle this and additionally the platform is wobbly if the crane is moved very fast, which is not what I want. I want to be able to achieve the same effect using CFrame instead of constraints. Of course, there will be a weld. I am thinking of using a Motor6D, but if it is not needed, then I will just utilize a normal weld.

If someone could help me with this, that would be amazing. Thank you for your time and help and I hope you have a good day.

This is probably not the best solution, but it was the first that came to mind, you could construct a new CFrame with lookat each time the rotation is updated, making use of the third parameter, up.

local part.CFrame = CFrame.new(part.Position, part.Position + part.CFrame.LookVector, Vector3.new(0,1,0)

this will make it maintain its horizontal orientation while also remaining upright because of the up parameter.

a possibly lighter method is using so an angle calculation like this.

local angle = math.acos(part.CFrame.LookVector:Dot(Vector3.new(0,1,0)) - math.pi/2 -- take away 90 degrees because the 'resting angle' is 90 degrees when upright.
part.CFrame *= CFrame.Angles(angle,0,0)

sorry if these don’t help, it’s pretty late and my brain kinda soupy.

4 Likes

How about a Motor6D mounting the seat assy. to the tilting section. You could take the tilt angle of the crane and when it changes set the Motor6D to that angle (or whatever the resultant angle should be).

2 Likes

@scripted_pj @Scottifly thank you both for your replies! I ended up using @Scottifly’s solution by basically setting the DesiredAngle on the Motor6D to the -DesiredAngle of the unit and it worked like a charm. I did come across a few problems with @scripted_pj reply, but the idea and foundation of that solution is wonderful. Again, thank you both for your replies. Have a nice one! Cheers!