Slerp Rotation Problem

I’m experiencing an issue with Quaternion.Slerp

Click this to watch: This video shows whats occurring with the game.

Here is the code im having an issue with:

public Vector3 newBreakerRotation = new Vector3(0, 0, 0);
public bool bRotating;
public float preRotate;
public float BreakerRotSpeed = 5f;

void Start() {
	newBreakerRotation = transform.eulerAngles;
}

void Update() {
	float rotate = Input.GetAxis("Rotate");
	
	if (!bRotating) {
		if ((rotate > 0f || rotate < 0f) && rotate != preRotate) {
			//Code that manipulates the value of newBreakerRotation.
			//If Q is pressed, the rotation's z axis is decreased by 90.
			//If E is pressed, the rotation's z axis is increased by 90.
			bRotating = true;
		}
	}
	
	if (transform.eulerAngles != newBreakerRotation) {
		transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.Euler(newBreakerRotation), BreakerRotSpeed * Time.deltaTime);
	}
	else {
		bRotating = false; // This never gets called. Why?
	}
}

Why doesn’t bRotating = false; get called ever?

Thank you!

Equality testing with floating point arithmetic is always a bad idea. Floating point values (that’s anything marked float or double, including the fields of Vectors and Quaternions) are notoriously inaccurate. Because of the way they are represented in the computer, they accumulate errors over time. These errors are usually not noticeable, but they do cause equality testing to fail. For example, you might be testing if a number is equal to 0.5, but over time, the errors accumulated means the number is actually 4.9999998721. This difference is so small it is unnoticeable to the naked eye, but these two values are not equal, so equality testing will fail.

So, what can you do to solve this? Well, it’s actually quite simple - use a margin of error, instead of an equality test. So rather than writing:

transform.eulerAngles != newBreakerRotation

Try something like this:

(transform.eulerAngles - newBreakerRotation).sqrMagnitude > 0.0001f

(Note that I’m using the square of the magnitude here, not the magnitude, for performance reasons - it saves on a costly square root call.)

You can tweak the value 0.0001f however you like. The smaller it is, the more accurate your results will be, but making it too small will cause your issue to reoccur. Making it larger will cause your rotation to stop early, but a value like 0.0001, or even 0.001, should be sufficient for good results. If you really want to to be accurate, you can also add a clause to snap the rotation to the desired value once you detect the difference to be below the margin of error.

BreakerRotSpeed * Time.deltaTime

This term does not scale between 0 and 1 with time. Slerp will not slerp

Hoeloe is spot on in the reason why it never reaches the ‘else’