- Home /
anyone can explain to me why I can't rotate continuously an object ?
Hi, I want to turn an object smoothly and continuously around the Y axis, So I have this code:
public class TempScript2 : MonoBehaviour
{
private float YAW_Rotation;
void FixedUpdate ()
{
YAW_Rotation +=3;
var startRotation = transform.rotation;
var endRotation = Quaternion.Euler(0, YAW_Rotation, 0);
transform.rotation = Quaternion.Lerp(startRotation, endRotation, Time.fixedDeltaTime);
}
}
This work great, however when I change the value of the increment to 4 (YAW_Rotation +=4), the object will rotate at some amount and then suddenly will start to rotate in the opposite direction at certain amounts.
any one can explain to me why this is happening ? I know that I should pass fixed values to the Lerp function to do a "real lerp", however I don't need the object to reach its destination, I want it to rotate while the user is pressing the arrows (YAW_Rotation +=3 * YAW_Input) (this is a helicpoter controller)...
Answer by Eno-Khaon · May 28, 2015 at 09:12 AM
The reason you're limited in this way is due to the nature of Euler Angles. By nature, there are an infinite number of ways to define any angle using Euler rotations. For example, a 180-degree rotation on the Y-axis is identical to a rotation of 180 degrees on both the X- and Z-axis with no Y-axis rotation.
This case is based on a different principle, however. Euler rotations are 0-360 degrees (exclusive). In other words, you never reach a 360-degree rotation, but instead reset to 0 degrees again. Because of this, you reach the point where your endRotation variable thinks it's a very low number and you quickly rotate the other direction until that value is greater than your starting rotation again.
You may want to try something like this instead:
public class TempScript2 : MonoBehaviour
{
private float YAW_Rotation;
void FixedUpdate()
{
Quaternion startRotation = transform.rotation;
Quaternion endRotation = Quaternion.AngleAxis(YAW_Rotation, Vector3(0, 1, 0));
// Option 1: Based on your previous script
transform.rotation = Quaternion.Lerp(startRotation, startRotation * endRotation, Time.fixedDeltaTime);
// Option 2: another means of handling the rotation
//var endRotation = Quaternion.AngleAxis(YAW_Rotation * Time.fixedDeltaTime, Vector3(0, 1, 0));
//transform.rotation *= endRotation;
}
}
That said, there are plenty of ways of approaching this beyond the two examples I gave, but AngleAxis calculates a rotation of any number of degrees as a Quaternion rotation function without factoring in Euler values' modulo operations (%).
An added note, the Vector3(0, 1, 0) can be replaced with Vector3.up. More importantly, it's simply the direction around which the rotation is applied. By association, if the rotation value is negative or the axis flipped upside down (-Vector3.up), the object would rotate the other direction instead.
Thanks @$$anonymous$$o $$anonymous$$haon for your response, however your solution did not work form me, I have the same effect (changing from Euler to AngleAxis have not changed anything)
Really? Putting together a quick test setup, I had a capsule (with child cube attached as an orientation marker) spinning in a single direction.
// C#
using UnityEngine;
using System.Collections;
public class TempScript2 : $$anonymous$$onoBehaviour
{
public float YAW_rotation = 90.0f;
void FixedUpdate()
{
Quaternion startRotation = transform.rotation;
Quaternion endRotation = Quaternion.AngleAxis(YAW_rotation, Vector3.up);
transform.rotation = Quaternion.Lerp(startRotation, startRotation * endRotation, Time.fixedDeltaTime);
}
}
(That said, if you're looking to rotate in this specific manner with no other intent in $$anonymous$$d (for instance, physics interactions), you could put it in "Update()" ins$$anonymous$$d of "FixedUpdate()" and replace "Time.fixedDeltaTime" with "Time.deltaTime", but that depends on whether you're looking for a smoother-looking rotation or a potentially more-interactive one)
I also noticed that when YAW_Rotation=308 (in my script), the rotation around the Y axis will start to decrease and the object will start to rotate in the inverse direction and it will return to the correct direction when YAW_Rotation=444. I don't know the relation between these numbers and the direction of the rotation.... I want my object to rotate continuously. I know that in increment of 3 for the YAW_Rotation will solve my problem (on my computer only maybe ?) but what if I want to increment it more later ?
this is the output of my log (where "Started here" mean that the object is start to rotate in the "wrong' direction, and "Ended here" mean that the object is now rotating in the "correct" direction:
Ah, okay. $$anonymous$$y mistake. I guess using Lerp wasn't letting it do what I'd hoped, so values of YAW_Rotation above 180 weren't behaving properly there.
That said, setting the endRotation value then just modifying the current rotation based on that was working for me up to rotations of 180 degrees per FixedUpdate() cycle, so how about this, ins$$anonymous$$d?
// C#
using UnityEngine;
using System.Collections;
public class TempScript2 : $$anonymous$$onoBehaviour
{
public float YAW_rotation = 90.0f;
void FixedUpdate()
{
YAW_rotation += (Time.fixedDeltaTime * 5.0f); // Proof of concept for endless acceleration of rotation
Quaternion startRotation = transform.rotation;
Quaternion endRotation = Quaternion.AngleAxis(YAW_rotation * Time.fixedDeltaTime, Vector3.up);
transform.rotation *= endRotation;
}
}
I have found that the problem is when you reach the 180 degree on the y axis, after that value, the y component of the Quaternion will be -1 (before that, it was +1).So when we increment YAW_rotation+=n, there is a time where a rotation of an angle of m degree will be easier for the Lerp function to do it in the inverse direction.