Animate individual letters in a string?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By Qws

For design reasons I would like to make individual chars/letters in a string fade-in into the dialogbox with animation player, one by one.

So imagine the string: “Hello”

I would like to see H transits from 1,1,1,0 opacity to 1,1,1,1 opacity. Something like

var text = "Hello"
text[0].modulate(1,1,1,0)
#In the animation player text[0] gets modulate of (1,1,1,1) after let say 1 sec.

Once that is done in the animation player. The next letter which is “e” should transits from 1,1,1,0 opacity to 1,1,1,1 opacity, this repeats till every letter of Hello is animated.

Problem is I can’t give individual char the proper property, let alone a key and value in the AnimationPlayer. Only the whole string “Hello” can fade in and fade out…

How to solve this? I don’t think creating labelboxes for every char forming a sentence is the solution…

On Twitter recently, I saw someone create a wavy text effect in their dialogue box. They did it by using an individual label per character, and animating the individual labels. Might be the easiest way.

Diet Estus | 2019-02-17 23:50

Don’t know whether this will solve your problem. You could use a RichTextLabel and edit each of the colors of the individual letters (or at least as the letters are printed out in the text box).

May not be a solution, but at least it’s a start.

Ertain | 2019-02-18 00:24

Problem is I can’t give individual char the proper property

Pretty sure creating a Label for every character is the solution.

Eric Ellingson | 2019-02-18 05:40

:bust_in_silhouette: Reply From: avencherus

As mentioned one approach is using the BBCodes in the RichTextLabel to manipulate individual characters.

You’d probably want to use some sort of timing data structure to manage your effect.

An example might look like this:

extends RichTextLabel # Godot 3.1 Beta


export var message = "Example Fade"
export var message_delay = 1.5
export var cascading_delay = 0.1

export var start_delay = 0.8


func _ready():

	set_physics_process(false)

	bbcode_enabled = true
	bbcode_text = message
	
	yield(get_tree().create_timer(start_delay), "timeout")
	
	fade_text(message, message_delay, cascading_delay)


func fade_text(string, duration, cascading_delay):

	char_timers = []

	var i = 0

	for c in string: # Characters in string.
	
		char_timers.append ({

			letter   = c,
			delay    = cascading_delay * i,
			count    = duration,
			duration = duration,
		})

		i += 1

	set_physics_process(true)


var char_timers

func _physics_process(delta):

	var is_active = false

	bbcode_text = ""
	
	var idx = 0

	for c_timer in char_timers:

		var color   = Color(1,1,1,0)

		if(c_timer.delay > 0.0):

			is_active = true
			c_timer.delay -= delta
			color.a = 1.0

		else:
			if(c_timer.count > 0.0):

				is_active = true
				c_timer.count -= delta
				color.a = max(c_timer.count / c_timer.duration, 0.0)


		bbcode_text += '[color=#' + color.to_html() + ']' + c_timer.letter + '[/color]'

	set_physics_process(is_active)