0
\$\begingroup\$

I am stuck with rotating a GameObject on the Z axis with easing.

I want to achieve an effect like in this game:

enter image description here

Here, the ring of targets starts rotating periodically. It starts slower, than rotation speed increases and again towards the end it decreases.

My speed of rotation is constant and I tried few approaches but with no luck. In my current code, I lerp new angle and then I substract previous angle from it to get actual angle needed for a turn.

private float degreesToTurn = 45;

private float t = 0;
private float previosDegrees = 0;
private float actualDegrees = 0;

void Update() {
    float degrees = GetDegreesToTurn();

    transform.Rotate(Vector3.forward * degrees);
}

private float GetDegreesToTurn() {
    t += 0.05f * Time.deltaTime * 10;

    actualDegrees = Mathf.Lerp(0, degreesToTurn, t);
    float rotateDegree = actualDegrees - previosDegrees;

    previosDegrees = actualDegrees;

    return rotateDegree;
}

I tried to increase t variable till I reached degreesToTurn / 2 but and then decrease it but that resulted not in easing but in rotating back.

Also I tried to use Quaternions but the problem is that I want to be able to rotate targets over 360 degrees which must result in N amount of spins. Quaternions don't allow me to do that.

\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

Here's a strategy you can use. Instead of using transform.Rotate that applies a rotational increment relative to your current rotation, set the whole rotation to some absolute orientation.

You can Lerp that absolute orientation between your start and destination orientations according to a progress parameter that goes from zero to one over the duration of the movement. Then you can apply any easing function you want to that progress value to change the movement.

// Easing function that gradually accelerates from rest
// and then gradually decelerates to a stop at the end.
float SmoothStep(float t) {
    t = Mathf.Clamp01(t); // Technically unused in this example.
    return t * t * (3 - 2 * t);
}

IEnumerator RotateWithEase(float relativeAngle, float duration) {
    // Remember where we started from.
    Quaternion startOrientation = transform.rotation;

    // Vary a "progress" parameter linearly from 0 to 1
    // over the duration of the movement.
    float speed = 1f/duration;
    for (float progress = 0f; progress < 1f; progress += Time.deltaTime * speed) {
        // Use the easing function to turn that linear motion
        // into an eased curve.
        float eased = SmoothStep(progress);

        // Apply your easing. 
        float currentAngle = relativeAngle * eased;
 
        // Rotate that far from wherever we started (in local coords).
        transform.rotation = startRotation * Quaternion.Euler(0, 0, currentAngle);       

        // Wait a frame, then resume the loop.
        yield return null;
    }

    // Snap exactly to the destination rotation at the end of the loop.
    transform.rotation = startRotation * Quaternion.Euler(0, 0, relativeAngle);
}
\$\endgroup\$
3
  • \$\begingroup\$ Hi DMGregory, thank you for your comment. Rotation in your solution works well but the problem with Quaternions is that it is not allowing me to really rotate 360 degrees or for example rotating for 450 degrees means that it will rotate only 90 degrees. \$\endgroup\$ Commented Apr 26, 2023 at 12:53
  • \$\begingroup\$ Ah, the example you showed seemed to only have short rotations of 60-180 degrees. You can apply the same trick to an angle that can exceed 180 though. I've edited to show this. \$\endgroup\$
    – DMGregory
    Commented Apr 26, 2023 at 13:30
  • \$\begingroup\$ Sorry about that, forgot to mention it. Your solutions works perfect! Thank you very much. \$\endgroup\$ Commented Apr 26, 2023 at 13:46

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .