Coding Quests
The Scroll Library
Tutorials

Godot 4 Tween Tutorial: Add Juice to Your Game

June 16, 20265 min read

"Juice" is the game dev word for all the little motion and feedback that makes a game feel good to touch. A button that pops when you hover it. A coin that arcs into your wallet. A character that squashes on landing. Most of it comes from tweens, and Godot 4's tween system is one of the nicest you'll use. Here's how to add the feel.

What a tween is

A tween smoothly changes a value from one number to another over time. Instead of snapping a button to twice its size, you tween its scale from 1 to 1.2 over a fifth of a second, and it grows. That's it. The magic is in how many things you can animate this way: position, scale, rotation, color, volume, anything that's a property.

You make one in code with create_tween():

GDScript
func _ready() -> void:
var tween := create_tween()
tween.tween_property(self, "modulate:a", 0.0, 1.0)

That fades the node out over one second by animating its alpha to 0. tween_property takes the object, the property (as a string, and you can target sub-properties like modulate:a), the final value, and the duration.

Easing makes it feel alive

A linear tween moves at a constant speed, which looks robotic. Easing curves fix that. set_ease and set_trans control the shape of the motion:

GDScript
var tween := create_tween()
tween.tween_property($Button, "scale", Vector2(1.2, 1.2), 0.2) \
.set_trans(Tween.TRANS_BACK) \
.set_ease(Tween.EASE_OUT)

TRANS_BACK with EASE_OUT gives that satisfying little overshoot, where the button grows slightly too big and settles back. TRANS_ELASTIC bounces. TRANS_SINE is a gentle ease. Try a few. The right curve is the difference between "fine" and "ooh."

Chaining and parallel

By default, tween steps run one after another, which is perfect for sequences:

GDScript
var tween := create_tween()
tween.tween_property(coin, "position", target_pos, 0.4)
tween.tween_property(coin, "scale", Vector2.ZERO, 0.1)
tween.tween_callback(coin.queue_free)

The coin flies to the target, then shrinks, then deletes itself. Each step waits for the last.

When you want steps at the same time, mark them parallel:

GDScript
var tween := create_tween().set_parallel(true)
tween.tween_property(popup, "scale", Vector2.ONE, 0.3)
tween.tween_property(popup, "modulate:a", 1.0, 0.3)

Now the popup scales up and fades in together.

The squash-and-stretch landing

Here's a classic bit of juice. When a character lands, squash them flat for an instant, then snap back. It reads as weight and impact:

GDScript
func land() -> void:
var tween := create_tween()
tween.tween_property(sprite, "scale", Vector2(1.3, 0.7), 0.05)
tween.tween_property(sprite, "scale", Vector2.ONE, 0.1) \
.set_trans(Tween.TRANS_BACK).set_ease(Tween.EASE_OUT)

Two lines of motion and your jump suddenly has heft.

Waiting on a tween

Sometimes you need to do something after a tween finishes. Tweens emit a finished signal you can await, which reads top to bottom like a little script:

GDScript
func play_intro() -> void:
var tween := create_tween()
tween.tween_property(title, "position:y", 100, 0.5)
await tween.finished
show_menu()

That await pattern comes straight from signals, and it's everywhere once you start animating.

Sprinkle it everywhere

Juice is the cheapest upgrade in game dev. The systems you've already built (menus, pickups, health bars) all get better with a tween or two. A health bar that slides instead of snapping. A menu button that pops on hover. Go add motion to one thing in your current project today, and you'll feel the difference immediately. The free Inventory System quest is full of spots begging for it.

FAQ

How do I create a tween in Godot 4?

Call create_tween() to get a Tween, then tween.tween_property(object, "property", final_value, duration). Godot 4 creates tweens in code rather than as nodes, and the tween runs automatically once you've defined its steps.

How do I make a tween run several animations at once?

Call set_parallel(true) on the tween, or use tween.parallel() before a step. Without it, steps run sequentially, one finishing before the next begins, which is what you want for multi-step sequences.

What's the difference between set_ease and set_trans?

set_trans picks the type of curve (like elastic, back, or sine) and set_ease picks how that curve is applied (in, out, or both). Together they shape the motion. A linear tween with no easing moves at constant speed and tends to look robotic.

godottutorialtweenanimation

Reading is the map. The quest is the territory.

Build this for real in the Inventory System Quest. It's free, no card needed.

Start the Quest
Written by Coding Quests

We teach Godot 4 by making you build complete systems: inventories, save systems, souls-like controllers, enemy AI. The scrolls are free. The quests are where it sticks.