【Godot】Smooth Animations with Tween

Created: 2025-12-06Last updated: 2025-12-16

Learn how to easily implement time-based value changes for UI effects, visual effects, and moving platforms using create_tween(), with practical code examples.

Overview

In games, objects moving smoothly feels much more natural and pleasant than instant teleportation. UI elements sliding in from off-screen, characters flickering when damaged, HP bars gradually decreasing—these "time-based value changes" can be easily implemented using Godot's Tween feature.

In Godot 4, you can easily create code-based animations by calling the create_tween() method.

Tween Basics: Start with One Line

The basic concept of Tween is simple: "Change a specific property of an object to a target value over a specified duration."

func _ready():
    # 1. Create a Tween object
    var tween = create_tween()

    # 2. Queue the animation
    # Change $Sprite2D's position property to Vector2(500, 300) over 1 second
    tween.tween_property($Sprite2D, "position", Vector2(500, 300), 1.0)

Tweens created with create_tween() automatically terminate and release from memory when all queued animations complete. This "fire and forget" convenience is one of Tween's greatest strengths.

Note: When the node that created the Tween is deleted with queue_free(), the Tween is automatically stopped and released. If you need animations to continue beyond the node's lifetime, consider binding the Tween to a different node with create_tween().set_ignore_time_scale(false).bind_node(another_node), or manage Tweens in an Autoload (singleton).

Practical Code Recipes

Recipe 1: UI Slide Animation (with Easing)

An effect where UI elements smoothly slide in from off-screen. Use set_trans() and set_ease() to achieve professional-looking motion.

func show_menu():
    var menu_panel = $MenuPanel
    menu_panel.visible = true

    var viewport_width = get_viewport_rect().size.x
    menu_panel.position.x = viewport_width

    var tween = create_tween()
    # TRANS_SINE: Sine curve interpolation
    # EASE_OUT: Decelerate at the end of animation
    tween.tween_property(menu_panel, "position:x", viewport_width - menu_panel.size.x, 0.5)\
         .set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_OUT)

set_trans specifies the interpolation method, while set_ease specifies where easing is applied during the transition.

Recipe 2: Smooth HP Bar Changes

Instead of instantly reflecting damage or healing, having the HP bar change gradually helps players intuitively understand the situation.

@onready var hp_bar: ProgressBar = $ProgressBar

func update_health_smoothly(new_health: float):
    var tween = create_tween()
    tween.tween_property(hp_bar, "value", new_health, 0.4)\
         .set_trans(Tween.TRANS_QUAD).set_ease(Tween.EASE_IN_OUT)

func _on_player_took_damage(damage_amount: float):
    var current_health = hp_bar.value
    update_health_smoothly(current_health - damage_amount)

Recipe 3: Damage Flicker Effect

Flickering effects to visually indicate invincibility frames when a character takes damage are another strength of Tween.

func start_invincibility_flicker():
    # Set up a loop to flicker 5 times
    var tween = create_tween().set_loops(5)

    # Change the modulate property's alpha value (opacity)
    tween.tween_property(self, "modulate:a", 0.3, 0.1)
    tween.tween_property(self, "modulate:a", 1.0, 0.1)

Advanced Techniques for Full Animation Control

Sequence and Parallel

  • Sequence: Writing consecutive tween_property calls executes them in order.
  • Parallel: Inserting parallel() between calls makes subsequent animations start simultaneously with the previous one.
func complex_animation():
    var tween = create_tween()
    var sprite = $Sprite2D

    # 1. First, move right over 1 second
    tween.tween_property(sprite, "position:x", 500.0, 1.0)

    # 2. Next, move down while simultaneously rotating 45 degrees
    tween.parallel().tween_property(sprite, "position:y", 300.0, 0.5)
    tween.parallel().tween_property(sprite, "rotation_degrees", 45.0, 0.5)

    # 3. Wait 0.5 seconds
    tween.tween_interval(0.5)

    # 4. Finally, fade out over 0.3 seconds
    tween.tween_property(sprite, "modulate:a", 0.0, 0.3)

Async Integration with await

When you want to perform specific actions after an animation completes, GDScript's await feature is extremely useful.

func play_and_destroy():
    var tween = create_tween()
    tween.tween_property(self, "scale", Vector2.ZERO, 0.5)

    # Wait at this line until tween's finished signal is emitted
    await tween.finished

    # Executed after animation completes
    queue_free()

Common Mistakes and Best Practices

Common MistakeBest Practice
Calling create_tween() every frame inside _process().Only call create_tween() when starting an animation. For continuous following, consider using lerp or other methods.
Starting new Tweens without stopping existing ones, causing conflicting movements.Stop existing Tweens with kill() before starting new animations (see code example below).
Connecting many processes to tween.finished signal, increasing complexity.Use await tween.finished and write the process as an async function for cleaner, more linear code flow.
Trying to implement all animations with Tween.Complex cutscenes involving multiple nodes and tracks are better suited for AnimationPlayer.

Using kill() to Prevent Tween Conflicts

var current_tween: Tween

func animate_to(target_position: Vector2):
    # Stop existing Tween if running
    if current_tween and current_tween.is_valid():
        current_tween.kill()

    # Create new Tween
    current_tween = create_tween()
    current_tween.tween_property(self, "position", target_position, 0.5)

Choosing Between Tween and AnimationPlayer

ComparisonTween (create_tween)AnimationPlayer
Best forCode-based dynamic animations, UI effects, simple value changesPre-defined complex sequences, cutscenes, character animations
SetupEasy (code-only)More complex (requires keyframe setup in editor)
FlexibilityHigh (can freely generate animations based on runtime values)Lower (primarily plays pre-defined animations)
Visual EditingNot possibleExcellent (can visually edit and preview in timeline)

Summary

Godot 4's Tween feature is a wonderful tool for easily and powerfully implementing code-based animations.

  • UI effects
  • Visual effects (flickering, fade-outs, etc.)
  • Creating moving platforms and mechanics

By leveraging Tween for these elements, you can dramatically improve your game's quality.