The appearance of text with animation

Godot version 4.2.1

Question

There is a Rich Text Label in my project. I’m changing the Visible characters so that the letters of the text appear one at a time. How do I make each letter appear slightly falling from above and going from transparent to normal, and when each letter appears, a sound is made?`

Here is an asset that may help you: Animated Text by indigobeetle

You can look at the code for the asset as well.

It is a plugin for Godot 3, not for godot 4.2

My mistake. But perhaps you can still learn how to animate text from looking at the code?

To understand how this plugin works, I need to almost completely rewrite all its code

Okay. I was just giving you an option to learn how to do what you want. Hopefully someone else comes along and provides an answer that is acceptable for you.

It’s possible but not easy. Here’s a similar effect:

RichTextEffect script:

@tool
class_name FlyRichTextEffect
extends RichTextEffect


var bbcode = "fly"
var data = {}
var delta:float = 0.0
var visible_characters:int = -1:
	set(new_value):
		visible_characters = new_value
		# Clean up the data if we are showing less characters than before
		if visible_characters < 0:
			data.clear()
		else:
			for data_range in data.keys():
				if data_range.x > visible_characters:
					data.erase(data_range)


func _process_custom_fx(char_fx: CharFXTransform) -> bool:
	if visible_characters < 0:
		return true

	var starting_x = float(char_fx.env.get('start', -10))
	var speed = float(char_fx.env.get('speed', 50))

	var range = char_fx.range

	# get the char data, set the default data if not available
	var char_data = data.get(range, {
		"offset_x": starting_x,
		"end": char_fx.transform,
		"finished": false
	})

	var finished = char_data.get("finished", false)

	# if not finished then update the offset_x until it reaches 0
	# update the char_fx values with that
	if not finished:
		var offset_x = char_data.get('offset_x', starting_x)
		offset_x = move_toward(offset_x, 0, delta * speed)
		if offset_x >= 0:
			offset_x = 0
			char_data['finished'] = true

		char_fx.offset.x = floor(offset_x)
		char_fx.color.a = remap(offset_x, starting_x, 0, 0.0, 1.0)

		char_data['offset_x'] = offset_x

	# update the data dictionary
	data[range] = char_data

	return true

RichTextLabelScript script:

@tool
extends RichTextLabel

var fly_effect:FlyRichTextEffect

func _ready() -> void:
	# Disable clip contents or the first glyph of each line will be clipped from the left
	clip_contents = false

	fly_effect = FlyRichTextEffect.new()
	custom_effects.clear()
	install_effect(fly_effect)

func _process(delta: float) -> void:
	fly_effect.delta = delta
	fly_effect.visible_characters = visible_characters

It’s pretty bad but you can get an idea on how to get whatever effect you are after. Basically, maintain a dictionary with glyph ranges as keys and the data you want to update as values. When changing the RichTextLabel.visible_characters value, it will remove old glyph values that have a range larger than the visible characters’ value. And for each glyph within the visible characters’ range that is not already in the dictionary with starting values, create a new entry in the dictionary and update its values.

If you need more control with how the visible characters animate in and out don’t use RichTextLabel.visible_characters and use a custom variable. Animate whatever you need and set the alpha of the characters that should be hidden to 0.

3 Likes

Thanks a lot