Help to understand how to use LERP (Smoothing Numbers)

G’Day, I’m attempting to smoothly change my numbers for my GUI but I can’t seem to properly understand how to do it. Basically I want my number to slowly increase/decrease depending on a variable.

I’ve tried many things like;

Watching Code Blue’s tutorial, but this just confused me more as it wasn’t working.

Using math.Approach, This one was confusing as I don’t know how to make it decrease




local health = math.Clamp( self:Health(), 0, 100 )
local smoothHealth = math.Approach( 100, health, 1 )



Using Lerp, This seemed to half work, but the number was not a full int




local health = math.Clamp( self:Health(), 0, 100 )
local smoothHealth = Lerp( 2 * FrameTime(), 100, health )



This is because you haven’t rounded the LERP’d value.
I believe his video explains it quite well, but linear interpolation based on the sample rate you’ve chosen (2xFrameTime) will never be a whole number unless the FrameTime value itself was always a whole number.

Since you’ve stated it “half worked” I’ll just assume you already have the value redefinded everytime your HUDPaint/other think hook is being called.



local smoothHealth = math.Round( Lerp( 2 * FrameTime(), 100, health ) )


math.Approach wouldn’t work in the case you posted since you are adding “1” to the display value without actually storing the progress. Lerp would probably be the most fit function for what you’re trying to do since it progresses faster at the beginning, than slower as it approaches the target value, which is great for HUD effects. If you want a consistent gain effect, than math.Approach would be better suited.

You should store the previous value of the health progress outside of the hook so that you can reference/update it every time it is called. Example:


local iLerpHealth = 0

hook.Add("", "", function()
	local pPlayer = LocalPlayer()
	
	-- Player exists - very rare case clientside
	if (pPlayer:IsValid()) then
		-- Max health not always 100 
		local iHealth = math.Clamp(pPlayer:Health(), 0, pPlayer:GetMaxHealth())
		
		-- If the Lerp target hasn't been reached
		if (iHealth ~= iLerpHealth) then
			-- Only take the integer value
			iLerpHealth = math.ceil(Lerp(2 * RealFrameTime(), iLerpHealth, iHealth))
		end
	end
end)

I’m drawing this on a draw hook and my circle and text seem to keep jumping from 98 - 99 even though it should be still on 80.




local health = math.Clamp( self:Health(), 0, 100 )
local smoothHealth = math.Round( Lerp( 2 * FrameTime(), 100, health ) )

draw.Circle( 2, -50, 35, 270, smoothHealth / 100 * 360, Color( 0, 156, 65 ) ) 

draw.DrawText( smoothHealth .. " HP", "DetailText" , 2, -58, Color( 0, 156, 65 ), TEXT_ALIGN_CENTER )




You didn’t change your code at all in respect to the health interpolation. Re-read my post above and store the Lerp result outside of the hook. Also, use Player:GetMaxHealth() instead of 100. in your clamp.

The number keeps jumping in-between 2 and 3




local smoothHealth = 0

function ENT:Draw()

    self:DrawModel()

    cam.Start3D2D( Pos + Ang:Up() * 17, Ang, 0.11 )

    	local health = math.Clamp( self:Health(), 0, 100 )

    	if health != smoothHealth then

    		smoothHealth = math.ceil( Lerp( 2 * RealFrameTime(), 0, health ) )

    	end

	 draw.Circle( 2, -50, 35, 270, smoothHealth / 100 * 360, Color( 0, 156, 65 ) ) 

	 draw.DrawText( smoothHealth .. " HP", "DetailText" , 2, -58, Color( 0, 156, 65 ), TEXT_ALIGN_CENTER )

    cam.End3D2D()

end



You’re setting the starting number for the Lerp to 0 every frame.

It should look like this:
[lua]
local smoothHealth = 0

function ENT:Draw()
– code–
smoothHealth = Lerp( 2 * RealFrameTime(), smoothHealth, health ) – don’t use math.ceil, it ruins the smoothness
– code–
end
[/lua]

You’re still using “0” as the start of your smoothHealth Lerp. It should be the previous smoothHealth value.

Thanks for all the help guys!

I can’t believe I looked straight over that when I was changing to your code