How to rotate an object around itself relative to the camera using Slerp?

I’m making a game and in this game I need to rotate a planted using the mouse left button, so I used this code:

public int speed;
public int lerpSpeed;
private float rotationX;
private float rotationY;
private Quaternion fromRotation;
private Quaternion toRotation;

void Update () {
rotationX -= Input.GetAxis ("Mouse X") * speed;
rotationY -= Input.GetAxis ("Mouse Y") * speed;
toRotation = Quaternion.Euler (rotationY, rotationX, 0);
transform.rotation = Quaternion.Slerp (transform.rotation, toRotation, Time.deltaTime * lerpSpeed);
}
The Slerp works great, however if I hold the mouse left button and move it to the left, making the planet spin 180 degrees around itself and then hold again the mouse left button and move it up, the planet will spin downward instead of spin upward.
I need help on how to solve this, because I have already searched a lot and nothing seems to work.

It may help to think of rotations in angle-axis format – any time you rotate an object, you’re spinning it some amount around some axis.

In Unity, an Euler angle rotates z degrees around the z-axis, x degrees around the x-axis, and y degrees around the y-axis, in that order. These rotations effect each other – once you’ve rotated x degrees around the x-axis, for example, you’ve pitched forward and changed the “up” axis that you’ll rotate around next.

You seem to be expecting rotation in a different order: y-axis first, then x-axis. You can’t do that in one call, but you can with two:

toRotation = Quaternion.identity;
toRotation *= Quaternion.Euler(0, rotationX, 0);
toRotation *= Quaternion.Euler(rotationY, 0, 0);

Now, that should solve your immediate problem.

That’s world-relative rotation, though. What if the camera isn’t aligned to the world? In that case, you can do basically the same thing: rotate around some axis, then rotate around some other axis… the only difference is that the two axes are camera-aligned, instead of world-aligned.

Suppose you have the camera’s transform:

Transform camTransform = Camera.main.transform;

You can build a new target rotation by spinning around the camera’s local axes:

Quaternion targetRot = transform.rotation;
targetRot *= Quaternion.AngleAxis(rotationX, camTransform.up);
targetRot *= Quaternion.AngleAxis(rotationY, camTransform.right);

And then rotate towards that:

float maxDegreesPerSecond = 10f;
transform.rotation = Quaternion.RotateTowards(transform.rotation, targetRot, maxDegreesPerSecond * Time.deltaTime);