Formula behind SmoothDamp

This question is somewhat unorthodox, I know, but please let me ask it anyway:

What's the formula (or method used) behind Mathf.SmoothDamp()?

I'd totally understand when you guys tell me that it is top secret. The thing is that I need to have something similar outside of Unity and just can't get behind that. I'm not lazy or anything, I'm not asking for finished and working code. I'd only like to get a hint into a useful direction.

In Unity 3.5 MonoDevelop you can jump into definition of Methods. For example SmoothDump:

using System;
public static float SmoothDamp (float current, float target, ref float currentVelocity, float smoothTime, float maxSpeed, float deltaTime)
	smoothTime = Mathf.Max (0.0001f, smoothTime);
	float num = 2f / smoothTime;
	float num2 = num * deltaTime;
	float num3 = 1f / (1f + num2 + 0.48f * num2 * num2 + 0.235f * num2 * num2 * num2);
	float num4 = current - target;
	float num5 = target;
	float num6 = maxSpeed * smoothTime;
	num4 = Mathf.Clamp (num4, -num6, num6);
	target = current - num4;
	float num7 = (currentVelocity + num * num4) * deltaTime;
	currentVelocity = (currentVelocity - num * num7) * num3;
	float num8 = target + (num4 + num7) * num3;
	if (num5 - current > 0f == num8 > num5)
		num8 = num5;
		currentVelocity = (num8 - num5) / deltaTime;
	return num8;

If you want something simpler try checking out the "Weighted Average" part in this very useful page:

I don't imagine this is what Unity uses, but I think it may get the job done in many cases.

You could add another level of smoothing to Magnus Wolffelt's suggestion:

Directly setting the target value: no smoothing, D0 discontinuity (=jump in position f(x)):


Using simple smoothing: D1 discontinuity (=jump in velocity f'(x), suddenly changing direction):

myValue = Mathf.Lerp(myValue, targetValue, 0.1f);

Using two-level smoothing: D2 discontinuity (=jump in acceleration f''(x) (which is not noticeable, since nature does the same all the time), resulting in linearly changing velocity and therefore smoothly changing position):

myIntermediate = Mathf.Lerp(myIntermediate, targetValue, 0.1f);
myValue = Mathf.Lerp(myValue, myIntermediate, 0.1f);

The two-level smoothing will also result automatically in a higher-order ease-in and ease-out, due to the acceleration effect.

This is somehow related to Bzier curves, maybe you can also get some ideas from there.

Good question.

While I don't know the exact formula inside that function, you can achieve similar results by a partial Lerp (implement your own if outside unity) every timestep, and save the value of the Lerp:

myValue = Mathf.Lerp(myValue, targetValue, 0.1f);

You should be aware however, that this is not timestep size independent, so if you change the timestep size, you will get different behaviour. Putting the delta time in the t parameter kind of reduces this change, but it will still change the behaviour if you change timestep size.

There is a correct (and slightly complex) way to implement this kind of smoothing to get the same behaviour independent of step size, but I don't have it at hand, and my math skills aren't that great.. :) I don't know if Unity implements this correctly or not. It is somewhat counter-intuitive that putting deltatime in the t parameter doesn't solve it, so people usually miss this.