Custom Easing Module for Manual Tweening

Overview

This is a lightweight easing module designed for developers who need manual, frame-based interpolation using RunService.

While TweenService works well for property-based animations, there are many situations where direct tween objects are either too restrictive or unnecessary — such as:

  • Custom animation systems
  • UI scaling and procedural effects
  • Interpolating non-tweenable values
  • frame-based updates

This module provides:

  • Full support for all standard EasingStyle types
  • Support for all EasingDirection modes
  • Strict Luau typing
  • Defensive argument validation
  • Manual interpolation via Heartbeat
    *Other useful methods

Why Not Just Use TweenService?

TweenService is excellent for property tweening, but it:

  • Requires Tween objects
  • Only works on tweenable properties
  • Does not provide direct eased progress per frame
  • Adds object overhead

This module instead exposes eased progress values directly, allowing you to apply interpolation however you want.

Grab the module: https://create.roblox.com/store/asset/137705773869840/Easing

Examples:

local Easing = require(path.to.Easing)

--a number to test in this example, in a real game this value might come from a
--heartbeat loop or a tween or whatever, should be between 0 and 1.
local number = 0.5

--get a eased value from a easing function
local easedValue = Easing.InOutSine(number)

--get a eased value from enums
local easedValue2 = Easing:FromEnum(Enum.EasingStyle.Elastic,Enum.EasingDirection.InOut,number)

-- get an eased value from a TweenInfo.
-- Note: TweenInfo.Time is treated as the normalized progress (0–1),
-- not duration in seconds.

local easedValue3 = Easing:FromTweenInfo(TweenInfo.new(
	number,
	Enum.EasingStyle.Elastic,
	Enum.EasingDirection.InOut
	))

--get a eased value from a lerp function, this is the equivalent of doing
--local lerped = math.lerp(1,100)
--local EasedLerped = Easing:FromEnum(Enum.EasingStyle.Elastic,Enum.EasingDirection.InOut,lerped)
local EasedLerpedValue = Easing:Lerp(1,100,number,Enum.EasingStyle.Sine,Enum.EasingDirection.InOut)

--smooth interpolate for animations or testing
local StartedAt = workspace:GetServerTimeNow()
--[[
StartedAt here can be a timestamp from the server to sync animations for new players.
this argument is optional, if not provided it will use the current time using workspace:GetServerTimeNow()
]]

Easing:SmoothInterpolate(Enum.EasingStyle.Quad,Enum.EasingDirection.InOut,10,function(easedProgress:number,RawProgress:number)
	--do whatever animation or thing that requires easing!
end,StartedAt)

print(`Easing Testing: {easedValue}, {easedValue2}, {easedValue3}, {EasedLerpedValue}`)

Bugs:
for now i have not encountered any errors with Easing, and i hope it stays that way, if you see any bugs/errors or have improvements ideas, please let me know!

i hope my module helps!

1 Like