0
\$\begingroup\$

I have written some code that creates a very nice uniform angular acceleration for an object moving around a circle. It effectively uses linear interpolation but ramps the interpolant such that the change is non-linear, hence the acceleration. The code is:

// Set the parameters to define the acceleration
float accelerationTime = 3f;
float startAngle = 0;
float endAngle = 180;
float currentAngle;
float startSpeed = 120;
float finalSpeed = 360;
float currentSpeed;
float radius = 3;
 
// Create the acceleration from 120 deg/s to 360 deg/s over a 180 degree angle within 3s
float t = 0;
accelFraction = 0;
Vector3 position;
while (accelFraction < 1f)
{
      t += Time.deltaTime;
      accelFraction = Mathf.Clamp(t / accelerationTime, 0, 1);
      currentSpeed = Mathf.Lerp(startSpeed, finalSpeed, accelFraction);
      float speedRatio = Mathf.Clamp(currentSpeed / finalSpeed, 0, 1);
 
      currentAngle = Mathf.Lerp(startAngle, endAngle, speedRatio * accelFraction);
   
      position = new Vector3(Mathf.Sin(currentAngle * Mathf.Deg2Rad), 0,
                             Mathf.Cos(currentAngle * Mathf.Deg2Rad)) * radius;
}

It allows me to accelerate from a start speed to an end speed, over a defined angular distance within a specific time. Great!

The problem is that I cannot figure out how to reverse this code to create the opposite effect, i.e. a deceleration. I have tried reversing the logic but it does not work, as counting downwards breaks the maths. Perhaps I am being obtuse but can anyone help here?

I would really like to keep my acceleration code the same; I suspect there is a simple tweak that I am missing. Any help is greatly appreciated!

\$\endgroup\$
3
  • \$\begingroup\$ Have you considered using AnimationCurves for this, to author the exact shape of acceleration curve you want? \$\endgroup\$
    – DMGregory
    Commented Nov 2, 2021 at 17:58
  • \$\begingroup\$ In my case the acceleration is uniform and occurs in a circular motion, over a defined angular coverage. In the above example from 0 to 180 degrees but I would like this to variable, which the above code provides. This solution works perfectly for acceleration but I just cannot get it to work the opposite way round for deceleration. I have never used animation curves before as I tend to just go with math. \$\endgroup\$
    – Cato
    Commented Nov 2, 2021 at 21:31
  • \$\begingroup\$ I think the problem lies in "reversing this code," and you haven't indicated what you tried. Just by a quick look, perhaps to decelerate, you would use 1-accelfraction when lerping for current speed. \$\endgroup\$
    – Yorik
    Commented Dec 3, 2021 at 22:03

1 Answer 1

1
\$\begingroup\$

I guess you could solve this problem mathematically. But I would solve this problem using an AnimationCurve instead. A very useful class which allows you to design things like ease-in and ease-out curves using a visual curve editor in the inspector.

My script:

public class Rotator : MonoBehaviour
{
    public float rotationDuration;
    public float startAngle;
    public float stopAngle;
    public AnimationCurve curve;

    private float currentRotationTime;

    void Update()
    {
        currentRotationTime += Time.deltaTime;
        var progress = curve.Evaluate(currentRotationTime / rotationDuration);
        var currentAngle = startAngle + (stopAngle - startAngle) * progress;

        transform.rotation = Quaternion.Euler(0f, 0f, currentAngle);
    }
}

(Instead of using that trigonometry logic of yours I am just rotating the object itself, but if you feed currentAngle into your code then it should work as expected)

How I drew the rotation curve in the inspector:

rotation curve

How it looks when I press play:

animation

\$\endgroup\$
1
  • \$\begingroup\$ I have experimented with this but I need the moving body to start and end at very specific speeds. I am not sure how that could be implemented using this method? Ideally I think using maths would be the most reliable solution. \$\endgroup\$
    – Cato
    Commented Nov 7, 2021 at 17:06

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.