How to make a flashing danger sign using tween

Godot Version

4.4beta

Question

Hi, I’m trying to make a very basic flashing danger sign using the Tween class. However, the current danger sign appears instantly and never disappears. What seems to be the problem here?

update:
Tween is non blocking. after fixing this by removing the function from process() and moving it into _on_value_changed(), there still seems to be some animation issue. The danger sign would pop up and disapper instantly rather than ease in and ease out smoothly.
I tried:
tw.tween_property($danger,“self_modulate:a”,255,flash_interval).set_ease(Tween.EASE_IN).set_trans(Tween.TRANS_LINEAR).from_current()
tw.chain().tween_property($danger,“self_modulate:a”,0,flash_interval).set_ease(Tween.EASE_IN).set_trans(Tween.TRANS_LINEAR).from_current()

but this still doesn’t seem to help. Why is it not smoothly transitioning?

Creating a tween on _process is a bad idea, you are making a new tween every frame and the overlapping effect will cause stuttering and flashing.

3 Likes

self_module.a is a property whose values are on the range of 0 to 1 (See Color — Godot Engine (4.3) documentation in English), therefore your code should be something like this:

var tw = create_tween()
tw.tween_property(sprite_2d, "self_modulate:a", 1, 1)
tw.tween_property(sprite_2d, "self_modulate:a", 0, 1)

BTW, to properly format code in your posts, follow these instructions: Make it easier for new users to format and preview code in their posts - #4 by gertkeno

2 Likes

1 - as said before, don’t put a tween in process.
tweens should be in a function and that function should be called by a signal or inside a function called by a signal, or on functions that run once like _ready().

from the docs:


var tween
func animate():
	if tween:
		tween.kill() # Abort the previous animation.
	tween = create_tween()

2 - you can LOOP a tween.

Tween set_loops(loops: int = 0)

Sets the number of times the tweening sequence will be repeated, i.e. set_loops(2) will run the animation twice.

Calling this method without arguments will make the Tween run infinitely, until either it is killed with kill, the Tween’s bound node is freed, or all the animated objects have been freed (which makes further animation impossible).

Warning: Make sure to always add some duration/delay when using infinite loops. To prevent the game freezing, 0-duration looped animations (e.g. a single CallbackTweener with no delay) are stopped after a small number of loops, which may produce unexpected results. If a Tween’s lifetime depends on some node, always use bind_node.

3 - don’t set current_color.a to 0 in-between Tweens. tweens are not executed in order of code, you are giving instructions to an object that runs after process.
either queue an instruction to set the a to 0 at the moment you want, or call a function to do so instantly with tween_callback().

4 -

tw.tween_property($danger,“self_modulate:a”,255,flash_interval).set_ease(Tween.EASE_IN).set_trans(Tween.TRANS_LINEAR).from_current()
tw.chain().tween_property($danger,“self_modulate:a”,0,flash_interval).set_ease(Tween.EASE_IN).set_trans(Tween.TRANS_LINEAR).from_current()

again, either set a function that creates the Color and changes it with tween_callback(), or use tween_method() to create the whole Color.

and I think with tween_property you need to do it like this:


tw.tween_property($danger.self_modulate, "a", 1.0, flash_interval)

Thanks, that seems to be the problem, I should read the doc more carefully.