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.

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