# Rotating a gameworld using quaternion

I'm a hobbyist programmer at best and I had an idea I wanted to test in Unity, I wanted to rotate the game world around 90 degrees, to this end I've been learning a tiny bit about quaternions, in this simple test I have a empty game object at position 0,0,0 and 2 cubes placed so only one will be in the foreground at once (both children of the empty game object). I simply want to rotate the parent object on a mouse up like so.

if (Input.GetMouseButtonUp(0)) {

Quaternion newrot = Quaternion.Euler (0,90,0);
transform.rotation = Quaternion.Slerp (transform.rotation,newrot,0.05f);

}
}


The problem I am having is that this does not do the rotation in a single click and never reaches 90 degrees, it only ever tends towards 90 (for fun I decided to click for 2 minutes and only got up to 89.99999 ... well you get the picture).

Can someone tell me what I am doing wrong and if there is a better way of doing this?

It looks like you're treating the Slerp method like you're starting a tween. "Start a new tween animation from here to there at this speed, okay... Go!" - with the expectation that it will carry out its work in parallel over the subsequent frames.

Slerp isn't that kind of method. It's just a math function that takes some inputs and gives you an output, exactly once, the frame that you call it, and never again until you explicitly call it again.

You can build your own tweening routine if you like. It would look something like this:

[Tooltip("Rotation speed in degrees per second")]
public float rotationSpeed = 180f;

Coroutine _turn;
Quaternion _targetRotation = Quaternion.identity;

void Update() {

// Using "Button" instead of "MouseButton" lets you or the
// player re-map this turn control without changing code.
if(Input.GetButtonUp("Turn")) {

// Increment our destination rotation by another 90 degrees.
_targetRotation *= Quaternion.Euler(0,90,0);

// If our tweening routine is already running, it'll handle this.
// Otherwise, we'll start an instance of it.
if(_turn != null)
_turn = StartCoroutine(TurnToTarget());
}
}

IEnumerator TurnToTarget() {

// Like a lot of floating point, waiting for exact equality here can
// let us get stuck. So we'll wait till we're "close enough".
while(Quaternion.Dot(transform.rotation, _targetRotation) < 0.9999f) {

// Rotate towards the target at a controlled rate over time.
transform.rotation = Quaternion.RotateTowards(
transform.rotation,
_targetRotation,
rotationSpeed * Time.deltaTime);

// Let the game run another frame before we loop again.
yield return null;
}

// Snap our rotation exactly to the target,
// in case we still had a few decimals off.
transform.rotation = _targetRotation;

// Mark the rotation action as complete.
_turn = null;
}


Note here I'm using the convenience method RotateTowards to get a controlled rotation speed. You can do this yourself with Slerp, taking on the speed adjustment math yourself. You can also use different easing functions to vary the speed of rotation over time, rather than keeping it exactly uniform.

I'm not able to test it right now (I'm on my phone).

I think what is happening is that this happens because each time you ask it to go from the current transform to the target transform, you specify the same percentage related to he scale (t).

Think of the "trick" question asking how long it would take to a ball that you drop to stop bouncing if each bounce is half the height of the preceding one. (Answer: it will never stop.)

To use the slerp method, you have to fix the starting and the end value, and make the t value change. (In your case, you make the end and the t value fixed and the start only changes.)

I suggest you take a closer look at the Quaternion.Slerp documentation. You'll notice they make the t value evolve with time.