Decision Tree — Tween vs AnimationPlayer
| Situation |
Choose |
| One-off UI juice, hover, popup, score count, recoil |
Tween (create_tween) |
| Authored multi-track clips, scrubbable timelines, blend trees |
AnimationPlayer / AnimationTree |
| Camera continuous follow behind a moving target |
Camera2D.positionsmoothing / spring follow — not a new Tween every process |
Menu motion while Engine.time_scale == 0 |
Tween with setignoretimescale(true) — MANDATORY [timescaleignoredui.gd](scripts/timescaleignored_ui.gd) |
| Retriggerable property (button spam, dodge cancel) |
Kill-before-recreate — MANDATORY [safetweeninterruption.gd](scripts/safetweeninterruption.gd) |
| Physics body / net correction motion |
TWEENPROCESSPHYSICS + resetphysicsinterpolation |
Available Scripts
MANDATORY: Read the script for the case above before writing tween glue.
[safetweeninterruption.gd](scripts/safetweeninterruption.gd)
MANDATORY for any retriggerable tween — kill active tweens before starting new ones.
[timescaleignoredui.gd](scripts/timescaleignoredui.gd)
MANDATORY for pause-menu / time_scale == 0 UI motion.
[nestedsubtweencutscene.gd](scripts/nestedsubtweencutscene.gd)
MANDATORY for composable cutscene timelines via tween_subtween.
[parallelpopupanimation.gd](scripts/parallelpopupanimation.gd)
set_parallel(true) + chain() for multi-property UI transitions.
[textcountermethodtween.gd](scripts/textcountermethodtween.gd)
tween_method for non-property values (score strings).
[customcurvetween.gd](scripts/customcurvetween.gd)
Curve resources for bespoke easing.
[camerashaketweenlogic.gd](scripts/camerashaketweenlogic.gd)
Procedural screen shake with looping tweens (offset, not follow).
[relativerecoiltween.gd](scripts/relativerecoiltween.gd)
asrelative() / fromcurrent() for recoil nudges.
[staggeredinventoryentry.gd](scripts/staggeredinventoryentry.gd)
Sequential collection entry on one Tween.
[loopedhovervfx.gd](scripts/loopedhovervfx.gd)
Infinite ping-pong ambient juice.
[juicemanager.gd](scripts/juicemanager.gd) / [tweenbuilder.gd](scripts/tweenbuilder.gd)
Central juice dispatch / builder helpers when many systems share feel presets.
NEVER Do in Tweening
- NEVER instantiate a Tween using
Tween.new() — Always use createtween() or gettree().create_tween() [3, 4].
- NEVER attempt to reuse a finished Tween — Single-use; recreate to replay [4].
- NEVER manually instantiate
PropertyTweener or CallbackTweener — Only via parent Tween methods [5].
- NEVER create an infinite loop containing only 0-duration animations — Freezes the engine [10].
- NEVER use multiple Tweens to animate the same property simultaneously —
kill() the old reference first [11, 12].
- NEVER use linear interpolation for UI/Juice — Prefer
EASEOUT + TRANSQUAD or EASEINOUT + TRANS_CUBIC [22].
- NEVER create tweens in
_process without guards — Creating 60 tweens per second will crash the app.
- NEVER skip
bind_node(self) for non-global tweens — Binding ensures death with the node [13].
- NEVER use 0-duration tweens for state changes — Set the property directly [20].
- NEVER forget to call
chain() when returning from set_parallel(true) [15].
Lifecycle Golden Path
var _tween: Tween
func animate_to(pos: Vector2) -> void:
if _tween and _tween.is_valid():
_tween.kill()
_tween = create_tween().bind_node(self)
_tween.set_ease(Tween.EASE_OUT).set_trans(Tween.TRANS_QUAD)
_tween.tween_property(self, "position", pos, 0.35)
MANDATORY pattern source: [safetweeninterruption.gd](scripts/safetweeninterruption.gd).
Camera Follow (Correct)
Continuous follow is not a Tween job:
extends Camera2D
@export var target: Node2D
func _ready() -> void:
position_smoothing_enabled = true
position_smoothing_speed = 5.0
func _physics_process(_delta: float) -> void:
if target:
global_position = target.global_position
If you must tween a one-shot camera punch/return, keep one Tween reference and kill before recreate — never createtween() inside unguarded process.
Expert Patterns (keep)
Physics-Sync-Tweening
func apply_physics_tween(target: Node3D, start_pos: Vector3, goal: Vector3) -> void:
target.global_position = start_pos
target.reset_physics_interpolation()
var tween := create_tween().bind_node(target)
tween.set_process_mode(Tween.TWEEN_PROCESS_PHYSICS)
tween.tween_property(target, "global_position", goal, 0.5)
Juice-Config-Resource
Store duration/trans/ease in a Resource (see juice scripts) so feel is data-driven.
Tween-Event-Sequencing
Parallel block → chain() → interval/callback → exit. Prefer [nestedsubtweencutscene.gd](scripts/nestedsubtweencutscene.gd) for nested modules.
Bezier-Path-Tween
Tween PathFollow2D.progress_ratio instead of hand-rolled Bezier math.
Deep recipes (on demand)
LLM-ignorance rule: if a general agent would not know it before reading, it lives here or in scripts/ — never delete, only move.
| Topic |
Reference |
| Chains, kill, gotchas |
[tween-recipes-and-gotchas.md](references/tween-recipes-and-gotchas.md) |
Reference
Progressive disclosure: open Official Documentation links only when researching a specific API; load Related Skills when routing to a peer domain — do not preload the whole lattice.
Official Documentation
- Tween — createtween, parallel/chain, loops, process mode, ignoretimescale, and kill/lifecycle rules.
- PropertyTweener — tweenproperty details: asrelative, fromcurrent, custom interpolators, and per-step ease/trans.
- MethodTweener — tweenmethod for non-property values (score counters, shader params, Curve-sampled motion).
- CallbackTweener — tweencallback for sequenced side effects without inventing fake 0-duration property steps.
- IntervalTweener — tweeninterval delays inside a single Tween timeline.
- SubtweenTweener — tweensubtween for nested cutscene modules under one parent timeline.
- Interpolation — lerp/smoothstep foundations behind easing choices and custom interpolators.
- Beziers, curves and paths — Curve/PathFollow patterns used when property tweens alone cannot describe the path.
- Introduction to the animation features — when Tween juice is enough versus AnimationPlayer/AnimationTree authored tracks.
- Using SceneTree — SceneTree.createtween and node lifetime when bind_node is not enough.
- Idle and Physics Processing — idle vs physics process modes for TWEENPROCESS_PHYSICS sync.
- Physics interpolation quick start guide — resetphysicsinterpolation when tweening transforms on interpolated bodies.
Related Skills
Prerequisites
- godot-project-foundations — scene tree, Node ownership, and resource basics before createtween/bindnode lifecycle patterns.
- godot-gdscript-mastery — typed callables, lambdas, and await/signal idioms used in tween_method and finished handlers.
Complements
- godot-2d-animation — sprite/skeleton motion that often coexists with Tween juice and needs shared kill/lifecycle discipline.
- godot-animation-player — authored clips for complex timelines; Tweens stay for runtime/procedural UI and one-off juice.
- godot-ui-containers — Control size/pivot/layout context for popup scale-fade and staggered inventory entry tweens.
- godot-signal-architecture — finished/callback wiring without dangling connections when Tweens are killed and recreated.
- godot-camera-systems — camera follow, shake offsets, and look targets driven by procedural Tweens.
- godot-resource-data-patterns — JuiceConfig-style Resources that store duration/trans/ease outside gameplay scripts.
- godot-particles — burst timing and one-shot VFX that should start from tween_callback steps, not parallel ad-hoc timers.
- godot-shaders-basics — shader params animated via tween_method / set when property paths are not enough.
Downstream / consumers
- godot-inventory-system — slot/item entry, drag feedback, and equip juice built on staggered and interruptible Tweens.
- godot-genre-card-game — hand arcs, draw/discard flights, and resolve polish that depend on Tween chaining.
- godot-ui-theming — theme-driven hover/focus motion that still needs safe Tween interruption under the same Control.
Master
- godot-master — library router and mirrored module entry for cross-skill discovery.