Overview
In action games, the "impact" when players land hits on enemies or receive damage is a crucial element that greatly affects the game's satisfaction. One of the simplest yet most effective techniques for conveying this impact is the white flash, where characters briefly glow white.
In Godot, you can easily implement this white flash effect with just a few lines of code and Tween, without needing difficult shader knowledge. The key is the modulate property.

How the modulate Property Works
modulate is a standard property on all 2D nodes that inherit from CanvasItem (Sprite2D, Label, ColorRect, etc.). By setting a Color to this property, you can multiply the color tint of that node (and all its children).
modulate = Color(1, 1, 1)(white): Same as the original color (default state)modulate = Color(1, 0, 0)(red): Only the R component of the texture remains, giving a reddish tintmodulate = Color(0.5, 0.5, 0.5)(gray): Overall darkermodulate = Color(1, 1, 1, 0.5)(semi-transparent): Alpha value controls transparency
Why Does It Glow White? HDR (High Dynamic Range) Effect
The most interesting feature of the modulate property is that color values can be set above 1. Normally, colors are expressed in a range from 0 (no light) to 1 (original color), but when you set modulate's RGB values above 1, the sprite is treated as HDR (High Dynamic Range) color and begins to glow as if illuminated from within. This creates a "blown out" expression, which is the principle behind white flash.
For example, setting modulate = Color(10, 10, 10) will make the sprite glow almost pure white regardless of the original texture color.
Basic Implementation: Smooth Transitions with Tween
A white flash is an animation sequence of "instantly turning white, then smoothly returning to the original color." To implement such time-based processing, Godot provides a very powerful and convenient feature called Tween.
Here's a reusable function that applies white flash to a character that takes damage (a node with a Sprite2D named sprite):
# Script on CharacterBody2D, etc.
# Manage Tween as instance variable (for controlling consecutive damage)
var flash_tween: Tween
# Function called externally when damage is received
func apply_damage_effect():
# ... Processing like reducing HP, starting invincibility time ...
# Start white flash processing
_start_white_flash()
# Internal function to execute white flash
func _start_white_flash():
# Cancel any already running Tween
if flash_tween and flash_tween.is_valid():
flash_tween.kill()
# 1. Instantly turn sprite white
$Sprite2D.modulate = Color(10, 10, 10) # Large values make it glow white
# 2. Create Tween and build animation to smoothly return to original color
flash_tween = create_tween().set_trans(Tween.TRANS_QUINT).set_ease(Tween.EASE_OUT)
# Change $Sprite2D's modulate property to Color(1, 1, 1) over 0.3 seconds
flash_tween.tween_property($Sprite2D, "modulate", Color(1, 1, 1), 0.3)
Code Explanation
- The
flash_tweeninstance variable manages the Tween. This allows canceling the previous Tween and starting a new flash when taking consecutive damage. - When
_start_white_flashis called,$Sprite2D.modulateis first set to aColorwith very large values. This instantly makes the sprite glow white. create_tween()creates a newTweenobject. Here, method chaining withset_transandset_easeconfigures the animation's easing. The combination ofTRANS_QUINTandEASE_OUTcreates sharp movement that starts quickly and ends slowly.tween_property()is the core of the animation. This method specifies "which object's" "which property" to change "to what value" "over how much time."- The
Tweenautomatically plays when created and is automatically destroyed when complete, so implementation is done.
Note: If large values like
Color(10, 10, 10)don't work, HDR may be disabled in project settings. In that case, try values aroundColor(2, 2, 2)toColor(3, 3, 3).
Common Mistakes and Best Practices
While effects using modulate are easy, there are several points for writing more polished code. Let's compare common beginner mistakes with recommended designs.
| Common Mistake | Best Practice |
|---|---|
Using counter variables in _process to manually animate | Use Tween or AnimationPlayer to describe animations declaratively |
Setting modulate directly to Color(0,0,0), making it black/invisible | To glow white, RGB values must be greater than 1. Even when darkening, leaving some brightness like Color(0.1, 0.1, 0.1) instead of Color(0,0,0) gives better texture |
| Mixing damage processing and effect processing in the same function | Use Signal to separate damage detection logic from visual effects. This prevents effect changes from impacting logic |
Calling create_tween() repeatedly without cleanup | When effects occur in rapid succession, kill() existing Tween before creating new ones to prevent unintended behavior |
Comparison with Alternative Patterns
modulate isn't the only way to implement white flash. Let's compare with the typical alternative: shaders.
| Feature | modulate + Tween | Custom Shader |
|---|---|---|
| Ease of Use | ◎ Very easy. Implementable in a few lines of GDScript | △ Requires learning shader language (Godot Shader Language) |
| Performance |