Home > Net >  Rotating an object between -45 and 45 degrees not behaving as expected
Rotating an object between -45 and 45 degrees not behaving as expected

Time:02-21

I'm trying to have an object oscillate between -45 and 45 degrees, and the following is the code I am using. Note that direction is initialized to 1, zRotation to 360, and speed to 100. This works perfectly fine. However, when I change speed to 1000, the object does a complete 360 rotation before continuing to oscillate correctly. I'm confused why that happens.

This is my code(inside the Update method):

zRotation  = speed * Time.deltaTime * direction;
var newRotation = 
   Quaternion.Euler(
      new Vector3(
         0, 
         0, 
         zRotation));

if (zRotation < 315)
   direction = 1;
if (zRotation > 405)
   direction = -1;

transform.rotation = newRotation;

I am using the values 315(-45 degrees) and 405(45 degrees) because it is easier to determine if my object has reached -45 and 45 degrees this way.

I'm aware that this behavior can easily and more cleanly be achieved using Lerp, but this is for an assignment and we haven't covered Lerp yet, so I don't want to use material that hasn't been taught yet.

CodePudding user response:

The problem is that you do not limit the zRotation values between your desired values. In the current state of your code you only rely on your computer being fast and having little Time.deltaTime values (the time elapsed since the last frame). If you have any kind of hiccup (which happens often in the first couple of frames after starting up), the Time.deltaTime value is going to be relatively large, resulting in a zRotation that is so large that it takes longer to return into the [-45...45] range. You can check this by adding a line of

Debug.Log($"Time: {Time.deltaTime} - Rotation: {zRotation}");

to your update method.

This way the following scenario can occur (each line is the log of a frame):

  1. Time: 0 - Rotation: 360
  2. Time: 0,02 - Rotation: 380
  3. Time: 0,02 - Rotation: 420
  4. Time: 0,333 - Rotation: 733,33

In the last step there was a deltaTime value that was so big that caused the zRotation to get loose and go really far from your desired range. If you limit the rotation values with

zRotation = Mathf.Min(Mathf.Max(zRotation, 315), 405);

You would not go out of the desired range. (Of course you have to update your if statements from < to <= or you could leave some kind of threshold in the Min(Max()) part.

I would also advise you use the modulo operator (%) and initialize the value of zRotation to 0 so that you don't have to constantly keep track of the 360-minAngle, 360 minAngle values, you could just use the angles in a much easier way and the modulo operator helps you stay in the [-360...360] range.

I updated your code:

public class Rotator : MonoBehaviour
{
    private float direction = 1;
    private float zRotation = 0;   // zRotation initialized to 0 instead of 360
    public float speed = 1000;

    void Update()
    {
        zRotation  = (speed * Time.deltaTime * direction) % 360;  // Use of the modulo operator
        zRotation = Mathf.Min(Mathf.Max(zRotation, -45), 45);   // Limiting the angles so the object does not 'spin out'

        //If you want to see what's going on in the log
        Debug.Log($"Time: {Time.deltaTime} - Rotation: {zRotation}");

        var newRotation =
           Quaternion.Euler(
              new Vector3(
                 0,
                 0,
                 zRotation));

        if (zRotation <= -45)  // LTE because of the limitation to -45
            direction = 1;
        if (zRotation >= 45)   /// GTE because of the limitation to 45
            direction = -1;


        transform.rotation = newRotation;
    }
}
  • Related