- Home /
The question is answered, right answer was accepted
Quaternion.RotateTowards() immediately snaps to target rotation
Hi, in the following code I want to roate an object with Quaternion.RotateTowards() inside the Update-Function. Unfortunately the Rotation doesn't take place over a period of time but immediately snaps to the target position(goalRot). the target position is a public Quaternion Variable I set in the Inspector. For the movementSpeed I allready applied values between 0.1f and 10f, makes no different.
if (rotateToWeight)
{
Debug.Log("rotation before: " + transform.rotation);
// The step size is equal to speed times frame time.
float step2 = movementSpeed * Time.deltaTime;
transform.rotation = Quaternion.RotateTowards(transform.rotation, goalRot, step2 );
Debug.Log("rotation: " + transform.rotation);
Debug.Log("goalRot: " + transform.rotation);
Debug.Log("Step: " + step2);
// Check if Rotation finished
if (gameObject.transform.rotation == goalRot)
{
// Stop Rotating
rotateToWeight = false;
Debug.Log("Finished ");
}
}
The console prints the following:
rotation before: (-0.5, -0.5, -0.4, 0.6)
rotation: (-1.0, 0.0, 0.0, 0.0)
goalRot: (-1.0, 0.0, 0.0, 0.0)
Step: 0,09783585
Finished
So, obviousliy the target rotation is allready reached after the first call of the function. No idea why. I would be glad if someone could help
Before jumping to conclusions here, you might want to actually log the goalRot ins$$anonymous$$d of the current rotation like so...
Debug.Log("goalRot: " + goalRot);
Also, unless you can read quaternions, it is usually easier to log the eulerangles of these rotations like so:
Debug.Log("goalRot: " + goalRot.eulerAngles);
Right. $$anonymous$$y guess is that the goalRot is not a valid normalized quaternion (probably tried setting eulerangles directly to the components of the quaternion). This would result in the dot product between the two quaternions to be way larger than 1. This means the quaternions would be considered equal. That means the angle between them is 0 and RotateTowards would simply return "to".
See the reference for
If the quaternion is not a unit quaternion, using eulerAngle on it wouldn't give you the right result. So logging the actual quaternion would make more sense when debugging. Though logging both would make most sense.
Like always for Quaternion related questions the reference to the Numberphile video on quaternions as well as the 3b1b video. Even when you're not understanding how a Quaternion works, it might help to actually recognise and distinguish them better from euler angles or other things.
You're both right, I tried to set Eulerangles to the Quaternion components and the angle was 0. $$anonymous$$anaged to solve it, thank you!
Answer by Ossi101 · Jul 17, 2019 at 03:06 PM
Do you have this code inside a loop in Update() ? I tried to replicate your situation and this was my result:
using UnityEngine;
public class RotateToQuaternionValue : MonoBehaviour
{
public bool rotateToWeight = false;
public Quaternion goalRotation = new Quaternion(-1.0f, 0.0f, 0.0f, 0.0f);
public float speed = 50.0f;
private void Update()
{
if (rotateToWeight)
{
float step = speed * Time.deltaTime;
transform.rotation = Quaternion.RotateTowards(transform.rotation, goalRotation, step);
if (transform.rotation == goalRotation)
{
rotateToWeight = false;
}
}
}
}
This is placed on the object you want to rotate. And in the inspector this is what it looks like:
Setting the bool starts the rotation and it turns off when it has reached the goalRotation value.
I hope this helps!