Skip to content

Instantly share code, notes, and snippets.

@Eideren
Last active October 19, 2021 04:43
Show Gist options
  • Save Eideren/54276cbbc448cf89f58e3a1a3b9aa3d0 to your computer and use it in GitHub Desktop.
Save Eideren/54276cbbc448cf89f58e3a1a3b9aa3d0 to your computer and use it in GitHub Desktop.
A replacement for the very common ``v = lerp(v, t, deltaTime)``, this one fixes the framerate dependant issue of the former while still providing easing in when close to target. Or just look at https://www.rorydriscoll.com/2016/03/07/frame-rate-independent-damping-using-lerp/ instead
// Example usage:
float dist = MathF.Abs( target - current );
current = Lerp( target, current, MoveToZeroEased( dist, deltaTime ) / dist );
/// <summary>
/// Moves <paramref name="distance"/> towards zero, the further away it is the larger the displacement.
/// Framerate independent.
/// </summary>
/// <param name="distance">The value you want to move towards zero</param>
/// <param name="timeDelta">The time between last and current call, multiply it to go faster</param>
/// <param name="easingRange">A constant which controls the speed increase per distance curve</param>
/// <remarks>
/// Time taken to travel is non-linear so for 100 units it'll take 10 sec but 200 is 14.1 sec.
/// </remarks>
static float MoveToZeroExp(float distance, float timeDelta, float easingRange = 2f)
{
var sign = MathF.Sign( distance );
double d = Math.Abs( distance );
d = Math.Pow(d, 1d / easingRange);
d -= timeDelta;
d = d < 0d ? 0d : d;
d = Math.Pow(d, easingRange);
d *= sign;
return (float)d;
}
// Increasing 'easingRange' will increase the speed in a non-linear way, to work around this issue
// we compute a 4PL symmetrical sigmoidal curve to ensure the scale of dist and easingRange does not affect the timeDelta/speed.
// The precision of this curve falls off fast outside of the [1.5,8] range but that shouldn't matter a whole lot as
// the function does not guarantee any specific time to completion and it still will produce framerate independent result
static float FixedSpeedGivenRange(float dist, float easingRange)
{
return dist * (1.848007f + 55.561453f / (1f + MathF.Pow(easingRange / 1.252288f, 3.513108f)));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment