Godot’s ease
function is both wonderfully powerful and surprisingly messy. What looks like a simple animation function actually behaves like four completely different functions depending on how you use it.
Just need to figure out the right curve value for your animation? Jump straight to the interactive playground below! Otherwise, let’s break this down step by step.
What Makes Animations Feel Natural?
Think about a ball rolling down a hill. It starts slow, picks up speed, then gradually slows down at the bottom. Or imagine jumping - you start fast, slow down at the peak, then speed up again as you fall.
Real things rarely move at constant speeds. That’s where easing comes in - it’s how we make game animations feel natural by adding this acceleration and deceleration.
How Easing Works
An ease function takes a progress value (from 0 to 1) and returns a modified value that creates more natural movement. Simple, right?
Well, Godot decided to make things interesting. Their ease
function takes two parameters:
x
: Your progress through the animation (0 to 1)curve
: A magic number that completely changes how the easing behaves
And when I say “completely changes,” I mean it. Let’s see how different values of curve
transform your animations:
Enjoy this interactive demo? I aim to build an intuition behind complex concepts through hands-on demos and clear explanations. Join other developers who want to understand the ‘why’ behind complicated mechanics!
The Four Hidden Functions
Let’s break down each type of easing you can get from this function. I’ve ordered these from most to least useful in typical game development:
1. Ease-In-Out (curve < -1): The All-Purpose Champion
Using curve = -5
This is probably what you want 80% of the time. It starts slow, speeds up in the middle, then slows down at the end - perfect for most game animations.
For the mathematically curious:
\begin{cases} \frac{1}{2}(2x)^{-\text{curve}} & x < 0.5 \\ 1 - \frac{1/2}(2-2x)^{-c} & x \geq 0.5 \end{cases}Common values:
-2
: Gentle ease (jumping, UI movements)-3
: Medium ease (character movements)-5
: Strong ease (dramatic effects)
# Perfect for a jumping animation
var jump_height = max_height * ease(progress, -3)
2. Ease-Out (0 < curve < 1): The Brake Pedal
Using curve = 0.2
Starts fast and slows to a stop. Think of a character landing from a jump or an object falling with air resistance.
For the mathematically curious:
1-(1-x)^{\frac{1}{\text{curve}}}
Popular values:
0.5
(1/2): Light braking0.33
(1/3): Medium braking0.2
(1/5): Heavy braking
# Perfect for falling with air resistance
var fall_distance = max_fall * ease(progress, 0.33)
3. Ease-In (curve ≥ 1): The Launch Pad
Using curve = 4
Starts slow and keeps accelerating. Great for things that build up speed, like a charging attack or a rocket launch.
For the mathematically curious:
x^{\text{curve}}
Common values:
2
: Light acceleration3
: Medium acceleration4
: Strong acceleration
# Great for a charging attack
var charge_power = max_power * ease(progress, 3)
4. Slow-Mo (-1 < curve < 0): The Weird One
Using curve = -0.3
This effect is sometimes also called ease-out-in (but I think that makes it a little confusing). It’s a bit strange - fast start, slow middle, fast end. Like a bullet-time effect. You probably won’t use this much, but it’s there if you need it.
As suggested by u/Major_Gonzo on Reddit, this could also be used for “movement slowed by terrain”.
For the mathematically curious:
\begin{cases} \frac{1}{2}(2x)^{-\text{curve}} & x < 0.5 \\ \frac{1}{2}(1-(1-2(x-0.5))^{-\text{curve}}) + 0.5 & x \geq 0.5 \end{cases}The Math Behind the Magic
Curious how this all works under the hood? Here’s Godot’s implementation:
double Math::ease(double p_x, double p_c) {
if (p_x < 0) {
p_x = 0;
} else if (p_x > 1.0) {
p_x = 1.0;
}
if (p_c > 0) {
if (p_c < 1.0) {
return 1.0 - Math::pow(1.0 - p_x, 1.0 / p_c);
} else {
return Math::pow(p_x, p_c);
}
} else if (p_c < 0) {
//inout ease
if (p_x < 0.5) {
return Math::pow(p_x * 2.0, -p_c) * 0.5;
} else {
return (1.0 - Math::pow(1.0 - (p_x - 0.5) * 2.0, -p_c)) * 0.5 + 0.5;
}
} else {
return 0; // no ease (raw)
}
}
Quick Reference
Here’s your cheat sheet for the curve
parameter:
What You Want | Curve Value | Example Use Case |
---|---|---|
Most Natural Movement | -2 to -5 | Character jumps, UI animations |
Deceleration | 0.2 to 0.5 | Landing, falling with resistance |
Acceleration | 2 to 4 | Charging attacks, takeoff |
Bullet Time | -0.3 to -0.8 | Special effects (rarely used) |
Common Pitfalls
A few things to watch out for:
- Don’t use
curve = 0
(returns 0) orcurve = 1
(no easing effect) - Values between -1 and 0 create that weird slow-mo effect
- The function clamps
x
between 0 and 1, so don’t worry about overshooting
Wrapping Up
The ease
function might seem overcomplicated at first, but its flexibility is actually pretty powerful once you get the hang of it. Start with ease-in-out (negative values) for most cases, and experiment from there.
Found this deep dive helpful? I break down complicated concepts with clear intuition and zero fluff. Subscribe below for regular explanations that make you a better developer!