I see questions come up quite often that have this underlying issue, but they're all caught up in the particulars of a given feature or tool. Here's an attempt to create a canonical answer we can refer users to when this comes up - with lots of animated examples! :)
Let's say we're making a first-person camera. The basic idea is it should yaw to look left & right, and pitch to look up & down. So we write a bit of code like this (using Unity as an example):
void Update() { float speed = lookSpeed * Time.deltaTime; // Yaw around the y axis using the player's horizontal input. transform.Rotate(0f, Input.GetAxis("Horizontal") * speed, 0f); // Pitch around the x axis using the player's vertical input. transform.Rotate(-Input.GetAxis("Vertical") * speed, 0f, 0f); } or maybe
// Construct a quaternion or a matrix representing incremental camera rotation. Quaternion rotation = Quaternion.Euler( -Input.GetAxis("Vertical") * speed, Input.GetAxis("Horizontal") * speed, 0); // Fold this change into the camera's current rotation. transform.rotation *= rotation; And it mostly works, but over time the view starts to get crooked. The camera seems to be turning on its roll axis (z) even though we only told it to rotate on the x and y!
This can also happen if we're trying to manipulate an object in front of the camera - say it's a globe we want to turn to look around:
The same problem - after a while the North pole starts to wander away to the left or right. We're giving input on two axes but we're getting this confusing rotation on a third. And it happens whether we apply all our rotations around the object's local axes or the world's global axes.
In many engines you'll also see this in the inspector - rotate the object in the world, and suddenly numbers change on an axis we didn't even touch!
So, is this an engine bug? How do we tell the program we don't want it adding extra rotation?
Does it have something to do with Euler angles? Should I use Quaternions or Rotation Matrices or Basis Vectors instead?


