Animation: AnimationPlayer, AnimationTree & Tweens

AnimationPlayer can keyframe any property of any node (position, modulate, frame, shader parameters), call methods, play audio, and more.

22.1 AnimationPlayer

AnimationPlayer can keyframe any property of any node (position, modulate, frame, shader parameters), call methods, play audio, and more. Create animations in the Animation bottom panel.

Other members: play_backwards(), stop(), pause(), seek(time), current_animation, is_playing(), get_animation("walk").length, has_animation(). Use Call Method tracks to trigger code (spawn a hitbox on frame 5) and set RESET animations for default values.

@onready var anim: AnimationPlayer = $AnimationPlayer

func _ready() -> void:
	anim.play("idle")
	anim.animation_finished.connect(_on_animation_finished)

func attack() -> void:
	anim.play("attack")
	anim.queue("idle")                  # play after the current one
	anim.speed_scale = 1.5

func _on_animation_finished(anim_name: StringName) -> void:
	if anim_name == &"death":
		queue_free()

22.2 AnimatedSprite2D (frame-by-frame)

Frames are stored in a SpriteFrames resource.

$AnimatedSprite2D.play("run")
$AnimatedSprite2D.flip_h = true
$AnimatedSprite2D.animation_finished.connect(...)
$AnimatedSprite2D.frame_changed.connect(...)

22.3 AnimationTree

AnimationTree blends animations from an AnimationPlayer using a graph: state machines, blend spaces (1D/2D), blend nodes.

In Godot 4.2+, AnimationPlayer and AnimationTree both inherit AnimationMixer (shared libraries, root motion).

@onready var tree: AnimationTree = $AnimationTree
@onready var playback: AnimationNodeStateMachinePlayback = tree["parameters/playback"]

func _physics_process(_delta: float) -> void:
	var input := Input.get_vector("move_left", "move_right", "move_up", "move_down")
	if input != Vector2.ZERO:
		tree.set("parameters/Idle/blend_position", input)   # BlendSpace2D inside state "Idle"
		tree.set("parameters/Walk/blend_position", input)
		playback.travel("Walk")                            # path-finds through the state machine
	else:
		playback.travel("Idle")
	tree.set("parameters/conditions/is_dead", health <= 0)  # transition condition

22.4 Tweens

Tweens animate properties from code — perfect for UI, juice, and one-off effects.

tween_property(obj, path, final, duration) Animate a property

.from(value) / .from_current() / .as_relative() / .set_delay(s) Property tweener options Call a function

tween_method(callable, from, to, duration) Call a method with interpolated values set_trans() / set_ease()

Curves: LINEAR, SINE, QUAD, CUBIC, BACK, ELASTIC, BOUNCE...

set_parallel(), parallel(), chain() Sequential vs parallel

set_loops(n), kill(), pause(), play(), is_running()

A node-bound tween (node.create_tween()) stops automatically when the node is freed. Kill a previous tween before starting a new one on the same property:

Godot 3 note: the Tween node with interpolate_property() + start() was replaced by create_tween().

func pop_in() -> void:
	scale = Vector2.ZERO
	var tween := create_tween()
	tween.tween_property(self, "scale", Vector2.ONE, 0.4)\
		.set_trans(Tween.TRANS_BACK).set_ease(Tween.EASE_OUT)

func flash_and_die() -> void:
	var tween := create_tween()
	tween.tween_property(self, "modulate", Color.RED, 0.1)
	tween.tween_property(self, "modulate", Color.WHITE, 0.1)
	tween.tween_property(self, "modulate:a", 0.0, 0.3)        # subproperty path
	tween.tween_callback(queue_free)                          # call at the end
	await tween.finished

func move_parallel() -> void:
	var tween := create_tween().set_parallel(true)
	tween.tween_property(self, "position", Vector2(300, 200), 1.0)
	tween.tween_property(self, "rotation", TAU, 1.0)
	tween.chain().tween_interval(0.5)                         # back to sequential
	tween.tween_method(set_label_value, 0, 100, 1.0)          # animate a method argument

func bob_forever() -> void:
	var tween := create_tween().set_loops()                  # infinite loop
	tween.tween_property($Sprite2D, "position:y", -8.0, 0.5).as_relative()
	tween.tween_property($Sprite2D, "position:y", 8.0, 0.5).as_relative()
var _tween: Tween
func fade_to(alpha: float) -> void:
	if _tween: _tween.kill()
	_tween = create_tween()
	_tween.tween_property(self, "modulate:a", alpha, 0.25)