Raise/Lower Object Height Based on Distance, with Easing

I'm trying to make an indicator object appear higher up in the sky the farther away a player is, up to a certain distance.

Basically, if the player is < 5 distance away, the object's height should be 1. If the player is > 60 distance away, the object's height should be 50. If the player's distance is between 5 and 60, the height of the object should be calculated based on the given scale, with an easing function applied so that it moves gradually to it's top and bottom locations.

This can be best illustrated with the attached graph that I created. The graph may not be perfect, but it should be close enough to get the general idea of what I'm hoping to achieve.

That said, I'd assume you'd need at least 5 variables... groundHeight, maxHeight, minHeight, maxDistance, and minDistance, but how would I use this information to calculate the expected height for a given distance?

This isn't related to a specific game engine and language isn't important. I happen to be working with Lua on my current project, but JavaScript, C#, or even pseudo-code solutions would help me understand how this is achieved.

• Looks like a job for cosine interpolation... (or any kind really -- just normalize your distance, apply your interp function, scale the output height and/or add ground offset) – A C Jul 21 '19 at 2:10
• This is a type of curve called a sigmoid. A handy version is available in many game development environments under the name SmoothStep. – DMGregory Jul 21 '19 at 5:04

First, we want to get out position between our min & max, normalized/clamped into a value between 0 (at/below the minimum) and 1 (at/above the maximum). That can look like this:

float t = Clamp(
(distance - minDistance)
/ (maxDistance - minDistance),
0, 1);


Then we can use a cubic SmoothStep function to bend this 0-1 value to have that signature sigmoid shape, easing in and out at the ends:

float sigmoid = 3*t*t - 2*t*t*t;


Lastly, we can use this sigmoid shape to blend between our outputs:

float height = minHeight + sigmoid * (maxHeight - minHeight);


Depending on your environment, you may have a built-in SmoothStep function that can do two or more of these steps in one fell swoop. Check the docs for your particular version for guidance, as I've seen some versions that take the distances and produce sigmoid (ie. the first two steps), and others that take the height min/max and t to produce the output (ie. the last two steps).