Skip to main content
Question Unprotected by DMGregory
Question Protected by DMGregory
Including another common code form
Source Link
DMGregory
  • 140.8k
  • 23
  • 257
  • 401

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!

Animated example of a first-person camera tilting sideways

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:

Animated example of a globe tilting sideways

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!

Animated example showing manipulating an object next to a readout of its rotation angles. The z angle changes even though the user didn't manipulate that axis.

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?

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; transform.Rotate(0f, Input.GetAxis("Horizontal") * speed, 0f); transform.Rotate(-Input.GetAxis("Vertical") * speed, 0f, 0f); } 

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!

Animated example of a first-person camera tilting sideways

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:

Animated example of a globe tilting sideways

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!

Animated example showing manipulating an object next to a readout of its rotation angles. The z angle changes even though the user didn't manipulate that axis.

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?

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!

Animated example of a first-person camera tilting sideways

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:

Animated example of a globe tilting sideways

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!

Animated example showing manipulating an object next to a readout of its rotation angles. The z angle changes even though the user didn't manipulate that axis.

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?

Tweeted twitter.com/StackGameDev/status/823595035652399106
edited tags
Link
DMGregory
  • 140.8k
  • 23
  • 257
  • 401
Source Link
DMGregory
  • 140.8k
  • 23
  • 257
  • 401

I'm rotating an object on two axes, so why does it keep twisting around the third axis?

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; transform.Rotate(0f, Input.GetAxis("Horizontal") * speed, 0f); transform.Rotate(-Input.GetAxis("Vertical") * speed, 0f, 0f); } 

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!

Animated example of a first-person camera tilting sideways

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:

Animated example of a globe tilting sideways

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!

Animated example showing manipulating an object next to a readout of its rotation angles. The z angle changes even though the user didn't manipulate that axis.

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?