Slow down in the same time over different distances


I’m trying to slow down a object over different distances in the same time, say 3 seconds.

My slow down code is.

function lerpSpeed (speed: float, lerpSpeedTime: float)
	incomingFlightSpeed = flightPathScript.flightSpeed;

	i = 0;
	while(i < 1)
		i += Time.deltaTime/lerpSpeedTime;
		i = Mathf.Clamp(i, 0, 1);

		flightPathScript.flightSpeed = Mathf.Lerp(incomingFlightSpeed, speed, i);


So I call it with.


In the picture below I’ve draw a bezier curve and at the last 8 flight points (the red and yellow spheres) I want to start the slow down from the yellow sphere to the last red sphere.

I get the distance in between each of the last 8 flight points and total them up to give me the total distance, I understand to get the time it will take to travel that distance is time = total distance/speed, but as I’m slowing the speed in my function above this will not work.

And because every bezier curve I generate is different, some stretched out, with total distances sometimes ranging from 30 to 8.

So I’m a bit stuck here, thought I’d get this one, but unless I’m missing something simple I can’t get my head around it, so any help would be greatly appreciated, thanks.

The code snippet above will give the inverse value. Below I modify it to make reading the curve easier.

Say your total distance of the bezier is 20 units. as you traverse the curve, your position (or distance from the end) in the curve will start to get smaller. It will start at 20 and as you move closer to the end it will be 19, 18, 15, 10, 5, etc. The remaining distance is something you will need to continuously track as you traverse the curve.

For the sake of continuity and clearly reading the animation curve, lets do it like this:

remainingDistance / totalDistance = a value between 0.0 and 1.0. 

20/20 = 1
15/20 = .75
10/20 = .5

So now, if we say:

1.0f - (remainingDistance / totalDistance) 

we will get the inverse of what we just did. this isnt necessary but it makes reading the animation curve a little easier from left to right. Evaluating the curve with this value will return a modified value based on that curve.

If you were to create a curve like this:

you could evaluate the curve with:

animCurve.Evaluate(1.0f - (remainingDistance/totalDistance))

For purposes of explanation, lets say you were 3/4ths the way through your bezier curve. That means if the total distance was 20, your remaining distance would be 5.

1.0f - (5/20) = 0.75f

Now look at the image i linked. At the bottom follow the value over to 0.75, follow it up until it reaches the curve. The returned value will be about 0.62f. Now we take the received value and multiply it by our max speed.

animCurve.Evaluate(1.0f - (distanceRemaining/totalDistance)) * maxSpeed

If the max speed at that time is 100, that means at this point in the curve we are traveling at a top speed of 62. As you can see, as you evaluate along the curve, the fastest you would be moving throughout the entire distance is halfway at 0.5. You can adjust this curve to be how you want. Something like this is what you want I am guessing :

This will automatically slow down and speed up depending on the point you are in the curve. The speed of the character would not matter as you could slow down/speed up and evaluate.

float finalSpeed = animCurve.Evaluate(1.0f - (remainingDistance/totalDistance)) * currentSpeed;

One thing to keep in mind is that if you set the beginning of the curve at a time of 0.0 and a value of 0.0, the returned value will be 0.0. Youll need to set the beginning of the curve to atleast 0.01 or do a check. if(returnedValue == 0) returnedValue = 0.01f

I have created a little demo script. I am creating the curve in the script, but you would want to hand tweak the curve to your desire.

SETUP: create 2 spheres. Place the script on one of the spheres and drag the other sphere into the “target” slot of the script. Press play. Notice how it starts slow, speeds up, and slows towards the end.