Unwanted and Strange Behaviors of BodyGyro

I am currently creating a 2D platformer that involves a rocket maneuvering multiple physics-based stages. The images and videos I have included are recorded in a test world where I am creating this movement system. The A and D keys are used to rotate the ship and the spacebar controls the thrust. I have created all of the basic functionality of this ship but there is one strange bug that remains. The ship is the StarterCharacter and is manipulated via UserInputService. I changed the humanoid state type to 16, the physics state, to make the humanoid ragdoll and stop orienting the ship automatically. The thrust of the ship uses a VectorForce and the rotation uses BodyAngularVelocity. The ship is held in place along the 2D axis by a BodyPosition to maintain a “2D” environment. When the ship bumps into things occasionally the physics will have it rotate on the X and Y axis which breaks the 2D effect. So the ship’s orientation on the X and Y is controlled by BodyGyro which for the most part works fine. Explaining 3D axes is confusing so I have placed a 3D indicator in the background of the test world. All of these forces are under the HumanoidRootPart of this StarterCharacter model.

Screenshot_1
Screenshot_2

The issue (I have included a video below) is that when the rocket points downwards for more than a second the BodyGyro rotates it along the X and Y axis to make it face upwards again. This doesn’t make much sense because the ship only moves on the Z-axis which the BodyGyro is set to ignore. I have no leads as to what could be causing this. The orientation of the ship is perfectly aligned so the “2D” rotation of the ship should have no influence on the other axes. Does anyone know what is causing this? Or maybe a viable alternative to BodyGyro that can hold the orientation in place?


I found this excerpt under troubleshooting in the documentation for BodyGyro. I set the Z axis’s max torque to 1 so it would be a non-zero number and saw zero difference in the behavior.

I solved this problem a while ago but forgot to update the topic because it is inactive.

I noticed that BodyGyro uses a target CFrame that it perpetually tries to achieve. The BodyGyro’s starting position was set to face upwards. This was significant because the ship was flipping when it faced the bottom 180 degrees on the Z-axis. I’ll call this area “the problem area” for simplicity. I set the target CFrame to be upside down and noticed that the problem area was also upside down now. This meant that the problem area was relative to the target CFrame and I could just continually update it so that the problem area was never where the ship was facing.

runService.RenderStepped:Connect(function()
	bodyGyro.CFrame = CFrame.Angles(0, 0, math.rad(humanoidRootPart.Orientation.Z))
end)

This fix ended up being very simple but I doubt RunService is the most performant solution.

1 Like