Tweener in Godot – Complete Guide

Welcome to our in-depth tutorial on Godot 4’s Tweener class—a powerful but often misunderstood feature that can bring a dynamic edge to your animations and gameplay. If you’re keen to add smooth transitions, intricate animations, or responsive action sequences to your games, you’re in the right place! By demystifying Tweeners, you’re taking a crucial step into the world of advanced game mechanics, elevating your developer toolkit, and bringing your game ideas to life with more polished and professional results. Stay with us as we explore the what, how, and why of Tweeners in Godot 4, and you’ll soon be animating with confidence and creativity.

What Is Tweener?

Tweener in Godot 4 refers to a set of classes designed to animate properties, call methods, and execute timed intervals with precision and ease. Abstract in nature, Tweeners can’t be instantiated directly; instead, they’re part of Godot’s robust animation system, generated through methods provided by the Tween class.

What Is It For?

Tweener classes serve a specific purpose. They take on varying animation tasks, such as:

  • Interpolating values over time for properties such as position, color, or opacity.
  • Invoking callback functions when certain animation milestones are reached.
  • Controlling the timing and sequencing of multiple animations to coordinate complex behaviors.

Why Should I Learn It?

Grasping the Tweener class opens up a world of possibilities for game developers:

  • Customization: Control every aspect of your animation to fit your creative vision without constraints.
  • Precision: Fine-tune timing and easing functions to create the desired feel and flow for in-game movements.
  • Optimization: Implement efficient animations that enhance the game experience without taxing the system.

By delving into these principles, you’ll not only improve your games aesthetically but also make the gameplay itself more engaging and interactive for players.

CTA Small Image
FREE COURSES AT ZENVA
LEARN GAME DEVELOPMENT, PYTHON AND MORE
ACCESS FOR FREE
AVAILABLE FOR A LIMITED TIME ONLY

Setting Up Basic Tweens

Before diving into complex animations, let’s first set up a basic tween to move a sprite object from one location to another on the screen. This will give us insight into how tweens are structured and used in Godot 4.

var tween = Tween.new()
add_child(tween)

tween.interpolate_property(
    $Sprite, # Object to apply the tween
    "position", # Property to be tweened
    $Sprite.position, # Initial value
    Vector2(400, 300), # Final value
    1.0, # Duration in seconds
    Tween.TRANS_LINEAR, # Transition type
    Tween.EASE_IN_OUT # Easing type
)

tween.start()

Once a Tween object is added as a child to the node, we can use the `interpolate_property` method to define what property we want to animate. In this case, the `position` of a Sprite.

Advanced Movement and Rotation

Now, let’s enhance our animation by making the sprite also rotate while it moves to the target location. We’ll be setting up a rotation tween alongside our movement tween.

tween.interpolate_property(
    $Sprite,
    "rotation_degrees",
    $Sprite.rotation_degrees,
    360,
    1.0,
    Tween.TRANS_QUAD,
    Tween.EASE_IN_OUT
)

tween.start()

Notice we have used `rotation_degrees`, not `rotation`. This is because Godot’s angle units are in radians by default, and `rotation_degrees` is simply more intuitive to work with.

Sequential and Parallel Animations

Sometimes we want animations to play one after the other (sequentially) or at the same time (in parallel). With tweens, we have the flexibility to do both.

Sequential Animations

To make our sprite move first and then rotate after the movement has finished, we could set up our tweens like this:

// Movement
tween.interpolate_property($Sprite, "position", $Sprite.position, Vector2(400, 300), 1.0, Tween.TRANS_LINEAR, Tween.EASE_IN_OUT)
tween.start()

# Wait for the completion of the first tween
yield(tween, "tween_completed")

// Rotation
tween.interpolate_property($Sprite, "rotation_degrees", $Sprite.rotation_degrees, 360, 1.0, Tween.TRANS_QUAD, Tween.EASE_IN_OUT)
tween.start()

Parallel Animations

If we want the sprite to move and rotate at the same time, we set up both tweens but call `start()` only once, after configuring both animations:

// Both Movement and Rotation configured before calling start
tween.interpolate_property($Sprite, "position", $Sprite.position, Vector2(400, 300), 1.0, Tween.TRANS_LINEAR, Tween.EASE_IN_OUT)
tween.interpolate_property($Sprite, "rotation_degrees", $Sprite.rotation_degrees, 360, 1.0, Tween.TRANS_QUAD, Tween.EASE_IN_OUT)

// Start both tweens at the same time
tween.start()

Callbacks and Signals

An important aspect of tweening is being able to execute code at certain points in the tween’s timeline, such as at the end of an animation. Godot’s Tween class uses signals to notify when animations start, stop, or complete.

// Connecting a tween's completion signal to a callable function
tween.connect("tween_completed", self, "_on_Tween_completed")

func _on_Tween_completed(object, key):
    print("Tween completed for: ", object.name, " Property: ", key)

In the code above, we connect the `tween_completed` signal of our Tween node to a function within the same script. Once the tween is completed, our function will be called automatically, and we can execute additional code dependent on the animation completion.

Using Tween to Scale Objects

Now let’s make our sprite grow and shrink, simulating a breathing effect. This can be a subtle but eye-catching effect for in-game items or characters to draw attention or signify importance.

// Scale up
tween.interpolate_property($Sprite, "scale", $Sprite.scale, Vector2(1.5, 1.5), 2.0, Tween.TRANS_QUAD, Tween.EASE_IN_OUT)

// Scale down, notice the chaining of tweens for seamless transitions
tween.interpolate_property($Sprite, "scale", $Sprite.scale, Vector2(1, 1), 2.0, Tween.TRANS_QUAD, Tween.EASE_IN_OUT, delay=2.0)

tween.start()

By animating the `scale` property, the sprite will increase in size to 1.5 times its original scale and then return back to its initial size. The `delay` parameter allows us to set a delay before the tween starts, which creates our seamless transition.

Color Interpolation

Let’s take a look at color animation using Tween. This is particularly effective for highlighting game objects or creating special effects like damage indication.

// Change color to red over time
tween.interpolate_property($Sprite, "modulate", $Sprite.modulate, Color.red, 1.0, Tween.TRANS_LINEAR, Tween.EASE_IN_OUT)

tween.start()

Here, the `modulate` property of the Sprite node is interpolated to the red color. This can be a neat trick to indicate that a character has taken damage, for example.

Executing Functions with Tween

Tween is not just for property animations; you can also use it to time function calls. This can be used to create delays before an action, or to space out function calls over time.

// Call a function with parameters after a delay
tween.interpolate_callback(self, 2.0, "my_function", "Hello, World!")

func my_function(message):
    print(message)

tween.start()

In the above code, `interpolate_callback` will call `my_function` with the string “Hello, World!” after a 2-second delay, illustrating how you can space out events in your game.

Tweening Custom Objects

Tweens aren’t limited to Godot’s built-in nodes—they can animate custom class properties as well. Here’s how to animate a custom resource with a tween.

// Assuming `my_resource` is a custom resource with a `value` property
var my_resource = preload("res://MyResource.gd").new()
tween.interpolate_property(my_resource, "value", my_resource.value, 100, 1.0, Tween.TRANS_LINEAR, Tween.EASE_IN_OUT)

tween.start()

This can come in handy when you have specific gameplay mechanics that require smooth changes over time, such as custom stats or even interpolated audio manipulation.

Stopping Tweens

Tweens can be stopped at any point, which is useful when an animation is suddenly no longer relevant due to game state changes.

// Stop all tweens for a specific object
tween.remove($Sprite)

// Stop a specific tween by property
tween.remove($Sprite, "position")

// Stop all tweens
tween.stop_all()

Knowing how to stop tweens is as crucial as starting them. It ensures that your game’s animations remain consistent with the player’s actions and the game’s logic.

Restarting Tweens

Sometimes, you may need to restart an animation—for example, when reusing the same animation multiple times, like a button pulsating effect.

// To restart the tween from its initial state
tween.reset_all()
tween.start()

Resetting can keep your code cleaner and your game more performant by reusing tweens instead of creating new ones for repetitive tasks.

Through these examples, we hope you’ve gained insights into the power and flexibility of the Tween class in Godot 4. As always, we encourage experimentation and exploration, since the best way to learn is by doing. Implement these examples in your own Godot projects and tweak them to suit your needs. Happy coding!Let’s further explore the capabilities of the Tweener class by diving into some practical examples. We’ll work with easing functions, chaining tweens for complex animations, handling tween interruptions gracefully, and utilizing the full power of signals. Experiment with these code examples in your own Godot projects to truly grasp the depth of what you can accomplish with tweens.

Easing Functions and Comfortable Movement

Tweens are not limited to mechanical, linear motions. Easing functions add naturalness to movements. Let’s create an animation where a sprite falls and bounces like a ball:

// Start the animation with a bounce effect
tween.interpolate_property($Sprite, "position", $Sprite.position, Vector2($Sprite.position.x, 500), 1.0, Tween.TRANS_BOUNCE, Tween.EASE_OUT)

tween.start()

By selecting `Tween.TRANS_BOUNCE` with `Tween.EASE_OUT`, the sprite will move to the y-coordinate of 500 with a bounce effect, simulating gravity and resilience.

Chaining Tweens for Complex Animations

Chaining tweens together can produce more elaborate animations. For instance, we can create an object that moves in a rectangular path indefinitely. This is how you can chain movements together using the `yield` method to wait for a tween to complete before starting the next one:

// Chain multiple movements
func start_rectangular_movement():
    tween.interpolate_property($Sprite, "position", $Sprite.position, Vector2(400, 100), 1.0, Tween.TRANS_LINEAR, Tween.EASE_IN_OUT)
    tween.start()
    yield(tween, "tween_all_completed")
    
    tween.interpolate_property($Sprite, "position", $Sprite.position, Vector2(400, 500), 1.0, Tween.TRANS_LINEAR, Tween.EASE_IN_OUT)
    tween.start()
    yield(tween, "tween_all_completed")
    
    tween.interpolate_property($Sprite, "position", $Sprite.position, Vector2(100, 500), 1.0, Tween.TRANS_LINEAR, Tween.EASE_IN_OUT)
    tween.start()
    yield(tween, "tween_all_completed")
    
    tween.interpolate_property($Sprite, "position", $Sprite.position, Vector2(100, 100), 1.0, Tween.TRANS_LINEAR, Tween.EASE_IN_OUT)
    tween.start()
    yield(tween, "tween_all_completed")
    
    # Repeat the sequence
    start_rectangular_movement()

start_rectangular_movement()

Notice how after each tween, we `yield` until `tween_all_completed` is emitted, and then start the next tween. Finally, we recursively call the method itself to repeat the sequence.

Handling Tween Interruptions Gracefully

Games are unpredictable, and sometimes we need to interrupt an ongoing tween to start a new one, perhaps due to player input. Here’s how we could handle such interruptions by first stopping the ongoing tween and then starting a new one:

// Stop any ongoing tween and start a new one
func move_to_new_position(new_position):
    tween.stop_all()
    tween.interpolate_property($Sprite, "position", $Sprite.position, new_position, 1.0, Tween.TRANS_SINE, Tween.EASE_IN_OUT)
    tween.start()

We call `tween.stop_all()` to ensure no other tweens affect the `$Sprite` before starting the new tween.

Utilizing Signals for Complex Game Flow

Signals in tweens can manage more complex game flows. For example, we might want a boss character to perform a special move after a dramatic entrance animation. Here’s how we could sequence this using signals:

// When a boss is about to enter, start an entrance animation
tween.interpolate_property($Boss, "position", $Boss.position, Vector2(screen_center_x, screen_center_y), 2.0, Tween.TRANS_QUAD, Tween.EASE_OUT)
tween.start()

// Connect the completion of the tween to a special move
func _ready():
    tween.connect("tween_completed", self, "_on_Boss_Animation_Completed")

// Callback that triggers boss's special move
func _on_Boss_Animation_Completed(object, key):
    if object == $Boss and key == "position":
        $Boss.special_move()

tween.start()

We connect the `tween_completed` signal to a method that triggers the boss’s `special_move` right as the entrance animation completes.

By combining these tweening techniques, you can create intricate and responsive animations that significantly enhance the player’s experience. With practice and creativity, you’ll be able to enact any number of dynamic scenarios, yielding a game that feels polished and captivating. Tweens are an invaluable tool, and mastering them will undoubtedly make your games stand out.

Continuing Your Godot Learning Journey

Having explored the essentials of Godot 4’s Tweener class, you’re likely eager to expand your game development skills further. We at Zenva are excited to support you on this journey and take it to the next level. Our Godot Game Development Mini-Degree is an excellent next step, offering a comprehensive deep-dive into game creation using the versatile Godot 4 engine.

The Mini-Degree covers a vast curriculum that ranges from 2D and 3D game development to mastering GDScript and understanding complex game mechanics. Through practical projects and quizzes, you’ll build your own games and a portfolio to showcase your newfound expertise. The courses are self-paced and designed for all skill levels, from beginners to those looking to polish their game development prowess.

For an even broader collection of knowledge, peruse our full range of Godot courses. The path from beginner to professional may be fraught with challenges, but with over 250 supported courses, Zenva provides you with the tools to navigate with confidence, earn certificates, and ultimately, achieve your game development goals.

Conclusion

We’ve just scratched the surface of what’s possible with Godot 4’s Tweener class, and there’s so much more to learn and explore in the realm of game development. The journey doesn’t stop here; every game you create is a new opportunity to apply, experiment with, and perfect your animation skills. The only limit is your imagination and the depth of your toolkit. With Zenva’s Godot Game Development Mini-Degree, you’re equipped to take the next big step.

Remember, game development is an art that combines creativity with technical skills. By continuing to build on your knowledge with our curated courses, you’re not just learning to code—you’re learning to bring your creative visions to life. So don your developer’s hat, fire up Godot 4, and let Zenva guide you through an epic adventure in game creation!

FREE COURSES
Python Blog Image

FINAL DAYS: Unlock coding courses in Unity, Godot, Unreal, Python and more.