Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I'm trying to make a plane rotate down a certain amount and 180 degrees horizontally over 2 seconds.

Basically I want it to take the plane 1 second to rotate to a horizontal-facing angle, then take the other second to rotate 180 degrees around to face the other direction.

The formula I'm currently using is:

    //If you're rotating, lower the speed and rotate the plane.
    if (rotate == 1 && rotationPhase > 0) {
        //If in phase 0, figure out which phase you need too go to.
        if (angle > 90 && rotationPhase == 1) {
            //Rotation phase 2 = rotating down
            rotationPhase = 2;
            rotationAngleTime = angle - 90;
        }
        else if (rotationPhase == 1) {
            //Rotation phase 3 = rotating up
            rotationPhase = 3;
            rotationAngleTime = 90 - angle;
        }

        //After phase 0, if in phase 1 begin rotating down, if in phase 2 begin rotating up.
        if (angle > 90 && rotationPhase == 2) {
            transform.Rotate(0, 0, -rotationAngleTime * (Time.deltaTime * (rotationSpeed / 2)));
            angle -= rotationAngleTime * (Time.deltaTime * (rotationSpeed / 2));
            if (angle > 89 && angle < 91) {
                angle = 90;
                rotationPhase = 4;
                rotationAngleTime = 180;
            }
        }
        else if (rotationPhase == 3) {
            transform.Rotate(0, 0, rotationAngleTime * (Time.deltaTime * (rotationSpeed / 2)));
            angle += rotationAngleTime * (Time.deltaTime * (rotationSpeed / 2));
            if (angle > 89 && angle < 91) {
                angle = 90;
                rotationPhase = 4;
                rotationAngleTime = 180;
            }
        }

        //After you have rotated to horizontal in phase 1/2, rotate around to face the other direction.
        if (rotationPhase == 4) {
            transform.Rotate(rotationAngleTime * (Time.deltaTime * (rotationSpeed / 2)), 0, 0);
            rotationAngle += rotationAngleTime * (Time.deltaTime * (rotationSpeed / 2));
            if (rotationAngle > 179) {
                rotationAngle = 0;
                rotationPhase = 0;
                rotationAngleTime = 0;
            }
        }
    }

I've tried many different things, but I can't figure out what to do.

EDIT: This seems to be a problem with Time.deltaTime. I can get the plane to rotate correctly, but for some reason it's not rotating over the right amount of time. I have a timer being subtracted by Time.deltaTime, and this animation happening, and the animation always finishes about half a second before the timer runs out.

share|improve this question
add comment

5 Answers 5

Use the line:

transform.Rotate(Vector3.up, horizontalAngle*Time.deltaTime);

to carry out the horizontal rotation over 1 second. Then use the line:

transform.Rotate(Vector3.right, verticalAngle*Time.deltaTime);

to carry out the second phase of your rotation. You can keep track of which rotation you're supposed to be applying using a method similar to the one you posted (the rotationPhase variable), but I would recommend using an enum for readability:

enum RotationPhase { Horizontal, Vertical };
public RotationPhase currentPhase = RotationPhase.Horizontal;

Finally, if you want to create a smoother rotation, you can look into the Vector3.SmoothDamp function; the documentation is here. In order to use this method you will first need to calculate the forward vectors of the plane as a result of each rotation. That vector becomes you're "target" vector. Then you can check if you've completed the rotation by checking the angle between the current vector and the target vector:

transform.forward = Vector3.SmoothDamp(transform.forward, target, ref vel, 1.0f, /*maxSpeed*/);
if(Vector3.Angle(transform.forward, target) < 1.0f) {
    // move on to next phase of rotation
}

Note that you would need to set up a variable to store the current velocity of the operation (vel in my example).

share|improve this answer
    
This doesn't seem to rotate the plane correctly, the plane rotates diagonally and gets stuck like that. –  Timothy Williams Mar 6 '12 at 16:39
add comment

To get how much we need to rotate per ms assuming the timedelta is in ms also.

total_ticks = 1000 * seconds
rotation_per_tick = angle / total_ticks

In update we rotate until elapsed time is up

if (total_ticks != 0) {
    if (total_ticks > Time.deltaTime) {
        transform.Rotate(rotation_per_tick * Time.deltaTime)
        total_ticks -= Time.deltaTime
    } else {
        transform.Rotate(rotation_per_tick * total_ticks)
    }
}
share|improve this answer
    
That code will not actually run, transform.Rotate is given insufficient arguments. Also, your calculation of the time of rotation is incorrect. Time.deltaTime returns the elapsed time in seconds, not milliseconds. –  ktodisco Mar 6 '12 at 1:48
2  
So? I've never used unity. I leave it up to the asker to deal with API specific issues. –  ClassicThunder Mar 6 '12 at 2:00
    
Something similar to that may work, however Disco is correct, Time.deltaTime returns in seconds not milliseconds. –  Timothy Williams Mar 6 '12 at 16:39
add comment

I strongly suggest looking at Itween, which is free, and has the ability to in a single line, do a "rotate x by 180 degrees taking 2 seconds, before calling procedure y". Performance is good even for mobile.

An example might be:

Vector3 customRotation = new Vector3(0f,0.5f,0f);
iTween.RotateBy(myGameObject, customRotation, 2f)

Noting that the rotation is normalized, so 1.0f == 360 degrees.

iTween also has an alternative syntax that opens up a span of additional options for this kind of rotation, for example adding easing curves or the possibility of a callback when the routine completes.

Vector3 customRotation = new Vector3(0f,0.5f,0f);
iTween.RotateBy(myGameObject, iTween.Hash("Amount",customRotation,"EaseType",iTween.EaseType.EaseOutCubic,"OnComplete","RunThisMethodNext");
share|improve this answer
    
This answer would be better with a link and an example. –  Byte56 Apr 19 '12 at 18:56
add comment
up vote 0 down vote accepted

EDIT: This makes the animation run properly, but it's still not running at the correct amount of time.

I figured out how to fix the problem myself, the solution was:

//If you're rotating, lower the speed and rotate the plane.
    if (rotate == 1 && rotationPhase > 0) {
        //If in phase 0, figure out which phase you need too go to.
        if (angle > 90 && rotationPhase == 1) {
            //Rotation phase 2 = rotating down
            rotationPhase = 2;
            rotationAngleTime = angle - 90;
        }
        else if (rotationPhase == 1) {
            //Rotation phase 3 = rotating up
            rotationPhase = 3;
            rotationAngleTime = 90 - angle;
        }

        //After phase 0, if in phase 1 begin rotating down, if in phase 2 begin rotating up.
        if (angle > 90 && rotationPhase == 2) {
            transform.Rotate(0, 0, -rotationAngleTime * (Time.deltaTime * (rotationSpeed / 2)));
            angle -= rotationAngleTime * (Time.deltaTime * (rotationSpeed / 2));
            if (angle > 89 && angle < 91) {
                angle = 90;
                rotationPhase = 4;
                rotationAngleTime = 180;
            }
        }
        else if (rotationPhase == 3) {
            transform.Rotate(0, 0, rotationAngleTime * (Time.deltaTime * (rotationSpeed / 2)));
            angle += rotationAngleTime * (Time.deltaTime * (rotationSpeed / 2));
            if (angle > 89 && angle < 91) {
                angle = 90;
                rotationPhase = 4;
                rotationAngleTime = 180;
            }
        }

        //After you have rotated to horizontal in phase 1/2, rotate around to face the other direction.
        if (rotationPhase == 4) {
            transform.Rotate(rotationAngleTime * (Time.deltaTime * (rotationSpeed / 2)), 0, 0);
            rotationAngle += rotationAngleTime * (Time.deltaTime * (rotationSpeed / 2));
            if (rotationAngle > 179) {
                rotationAngle = 0;
                rotationPhase = 0;
                rotationAngleTime = 0;
            }
        }
    }
share|improve this answer
1  
If I were you I would look into Quaternions and rotational interpolation, they are very common mathematical topics that have many resources and will give your rotation a more natural and smooth feel. (You will see horrible jumps with 3D Euler rotation) –  Matt Jensen Mar 6 '12 at 22:23
    
The animation in this fix is perfectly fine, no jumps. The only problem is I can't seem to accurately get it to draw over 2 seconds. I have a timer that runs for 2 seconds for the rotation animation, and the code I linked above should technically run over two seconds, but it runs slightly under two seconds (about 1.5 or 1.6) I don't see how you're supposed to do something over an accurate amount of time. –  Timothy Williams Mar 7 '12 at 16:21
add comment

The BeginRotate and EndRotate events of KetticRotater control pass a BeginRotateEventArgs with one of the From, To, and Cancel properties to control the rotation from and to a certain amount of time.

share|improve this answer
    
-1; this has only the vaguest relationship to the question that was posed, and isn't a very good answer regardless (being essentially a link-only answer). –  Josh Petrie Feb 21 at 4:56
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.