--- name: tween-animation description: Use when implementing tweens — property animation, method tweening, chaining, parallel sequences, easing, and common UI/gameplay motion recipes --- # Tweens in Godot 4.3+ All examples target Godot 4.3+ with no deprecated APIs. GDScript is shown first, then C#. > **Related skills:** **animation-system** for AnimationPlayer/AnimationTree (keyframe-based), **godot-ui** for UI transitions, **shader-basics** for tweening shader parameters, **camera-system** for camera shake and transitions, **math-essentials** for easing curves and interpolation math, **particles-vfx** for code-driven VFX timing and sequencing. --- ## 1. Core Concepts ### Tween vs AnimationPlayer | Feature | Tween (code-driven) | AnimationPlayer (data-driven) | |-----------------|--------------------------------------------|--------------------------------------------| | Setup | Code only — no editor needed | Animation panel with keyframes | | Best for | Procedural motion, UI transitions, VFX | Complex multi-track, artist-driven clips | | Reusability | Recreated per use — lightweight | Saved as resources, reusable across scenes | | Blending | No — one tween per property at a time | Yes — AnimationTree supports blending | | Method calls | `tween_callback()` at any point | Call Method tracks at keyframed times | **Rule of thumb:** Use Tweens for one-off procedural animations (fade in, bounce, slide). Use AnimationPlayer for repeating, artist-tuned animations (walk cycle, attack sequence). ### Creating a Tween Tweens are created from any `Node` and auto-bind to it. When the node is freed, the tween stops automatically. ```gdscript # Creates a tween bound to this node var tween := create_tween() tween.tween_property(self, "position", Vector2(400, 300), 1.0) ``` ```csharp var tween = CreateTween(); tween.TweenProperty(this, "position", new Vector2(400, 300), 1.0f); ``` > **Important:** Each call to `create_tween()` creates a new tween. Previous tweens on the same property are **not** automatically killed — they compete. Kill old tweens before creating new ones on the same property if you don't want conflicts. --- ## 2. Tweener Types ### tween_property() — Animate any property ```gdscript var tween := create_tween() # Animate position over 0.5 seconds tween.tween_property($Sprite2D, "position", Vector2(200, 100), 0.5) # Animate modulate alpha (fade out) tween.tween_property($Sprite2D, "modulate:a", 0.0, 0.3) ``` ```csharp var tween = CreateTween(); tween.TweenProperty(GetNode("Sprite2D"), "position", new Vector2(200, 100), 0.5); tween.TweenProperty(GetNode("Sprite2D"), "modulate:a", 0.0f, 0.3); ``` **Sub-property access:** Use `:` to target individual components — `"position:x"`, `"modulate:a"`, `"scale:y"`. ### tween_callback() — Call a method at a point in the sequence ```gdscript var tween := create_tween() tween.tween_property(self, "position", Vector2.ZERO, 0.5) tween.tween_callback(func(): print("Arrived!")) tween.tween_callback(queue_free) ``` ```csharp var tween = CreateTween(); tween.TweenProperty(this, "position", Vector2.Zero, 0.5f); tween.TweenCallback(Callable.From(() => GD.Print("Arrived!"))); tween.TweenCallback(Callable.From(QueueFree)); ``` ### tween_interval() — Wait/delay between steps ```gdscript var tween := create_tween() tween.tween_property(self, "modulate:a", 0.0, 0.3) # fade out tween.tween_interval(1.0) # wait 1 second tween.tween_property(self, "modulate:a", 1.0, 0.3) # fade back in ``` ```csharp var tween = CreateTween(); tween.TweenProperty(this, "modulate:a", 0.0f, 0.3); tween.TweenInterval(1.0f); tween.TweenProperty(this, "modulate:a", 1.0f, 0.3); ``` ### tween_method() — Animate a custom method with interpolated values ```gdscript # Animate a method that receives interpolated float values func _ready() -> void: var tween := create_tween() tween.tween_method(_set_health_bar, 100.0, 0.0, 2.0) func _set_health_bar(value: float) -> void: $HealthBar.value = value $HealthLabel.text = "%d%%" % int(value) ``` ```csharp public override void _Ready() { var tween = CreateTween(); tween.TweenMethod(Callable.From(SetHealthBar), 100.0f, 0.0f, 2.0f); } private void SetHealthBar(float value) { GetNode("HealthBar").Value = value; GetNode