I have a very simple script that I wish to rotate something on the X-axis, and I'd expect the other two axes to stay put(they flip between 0 and 180), and only X to change.
Below you can see the code intended to do just that.
public class TestScript : MonoBehaviour
{
private void Start()
{
transform.eulerAngles = Vector3.zero;
Debug.Log($"start rotation: {transform.eulerAngles}");
}
private void Update()
{
float time = (Time.time - 1f) * 10f;
if (time < 0f || time > 1f)
{
return;
}
Vector3 rotation = transform.eulerAngles;
float x = Mathf.Lerp(170f, 0, time);
rotation.x = x;
transform.eulerAngles = rotation;
Debug.Log($"rotation: {transform.eulerAngles}, x: {x}");
}
}
The output from the console. You can clearly see that the rotation does not go from 170 to 0, but from 0 to 90 and then back to 0.
Now, I'm pretty sure this has something to do with quaternions and their identity, but not sure how can this be avoided
PS: The same idea but for Y and Z works just fine.
Now, I'm pretty sure this has something to do with quaternions
Well the real culprit is Euler angles.
If we take a look at your code:
Vector3 rotation = transform.eulerAngles;
float x = Mathf.Lerp(170f, 0, time);
rotation.x = x;
transform.eulerAngles = rotation;
Debug.Log($"rotation: {transform.eulerAngles}, x: {x}");
...we can see you are performing rotations via transform.eulerAngles
. The thing about 3D rotations is that you should avoid using Euler due to their limitations and problems (gimbal lock anyone) and use quaternions instead. The latter is the source of truth.
Unity (my emphasis):
When you read the.eulerAngles property, Unity converts the Quaternion's internal representation of the rotation to Euler angles. Because, there is more than one way to represent any given rotation using Euler angles, the values you read back out may be quite different from the values you assigned. This can cause confusion if you are trying to gradually increment the values to produce animation.
...which is exactly what is happening with your code.
Consider this:
Notice anything about the 23.5
and the 156.5
?
23.5 + 156.5 = 180
In other words both will lead to the same rotation as per "there is more than one way to represent any given rotation" .
An arguable simpler approach is:
public class RotateWithTime : MonoBehaviour
{
[SerializeField,Tooltip("Rotation rate in degrees/second")]
private Vector3 rotationSpeed; // e.g. (30,0,0) for 30 rads/sec X-only
private void Reset()
{
rotationSpeed = Vector3.zero;
}
// Update is called once per frame
void Update()
{
var amount = rotationSpeed * Time.deltaTime;
transform.Rotate(amount);
}
}
In order to avoid this question becoming a chameleon question due to the lack of info in the initial question, I have asked a new one and will be closing this one. You can find it here
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.