0

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!

Cato
  • 83
  • 7
  • Have you considered using AnimationCurves for this, to author the exact shape of acceleration curve you want? – DMGregory Nov 02 '21 at 17:58
  • 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. – Cato Nov 02 '21 at 21:31
  • 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. – Yorik Dec 03 '21 at 22:03

1 Answers1

1

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

Philipp
  • 119,250
  • 27
  • 256
  • 336
  • 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. – Cato Nov 07 '21 at 17:06