A problem with Quaternion.Slerp

I have a spaceship with a Rigidbody which can be controlled by the user. Inside FixedUpdate I modify x and z rotation to turn it upright while the user still controls the spaceship. It’s a kind of an autopilot for getting it back to horizontal alignment.

transform.rotation = Quaternion.Slerp( transform.rotation, Quaternion.Euler(0.0f,transform.rotation.eulerAngles.y,0.0f), Time.deltaTime*3.0f );

A rotation around the x axis is corrected by the autopilot (Slerp) very well. A rotation around the z axis will be corrected also, but the spaceship gets always a slight rotation around the y axis (counter clockwise).

I’m wondered because I think normally the line above shouldn’t modify the y axis.

What’s my fault here?

Don’t know if this is the problem but if this is in FixedUpdate it should be using Time.fixedDeltaTime instead of Time.detlaTime.

Whether or not your code alters the y axis depends on your starting transform.rotation and it’s Euler representation.

I will give a quick example to show the down falls of Eulerian orientations:

Let’s say you have an object with eulerian rotation (90, 90, 0)

and you want to rotate it to (0, 0, 270), it seems like this is quite a weird rotation we have to rotate -90 on the x-axis, -90 on the y axis and -90 on the z axis.

That won’t happen however, because it is not the shortest route. (90, 90, 0) is actually equal to (90, 0, 270). And so the rotation we get is just -90 on the x-axis!

I don’t actually know for sure that will happen in practice, but the point is, when you use eulerian rotations, things get weird. Unfortunately it’s the rotation type we all (think we) know and love, but you have to give them the bench if you don’t want buggy orientations.

The best way I can think of, if you want to keep your forward direction, but turn your ship upright would be as follows:

Transform yourShip;
Quaternion targetRotation = Quaternion.LookRotation(yourShip.forward, Vector3.up);
transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, Time.deltaTime*3.0f);

Or you could use the Transform.Rotate method quite nicely for this!

Scribe