Timing character printing

Godot Version

v4.3.stable.official [77dcf97d8]

Question

I am working on a visual novel and I want to have characters render at a variable speed. I have the _process looking for ui_accept keypress to speed up the text rendering. And it loops through multiple times until the _countdown reaches 0 then it prints the next character.

The problem is I can’t come up is the SOMETHINGs to set the countdown to start with and the decrementing to step it down by. I would prefer the _currspeed to a whole number of how many characters a second are displayed. But my math-fu is not working.

func _process(delta: float) -> void:
	if Input.is_action_just_pressed("ui_accept"):
		if _is_playing:
			_currspeed = text_faster
		else :
			_forward()
	if Input.is_action_just_released(("ui_accept")):
		_currspeed = text_speed
	
	if _play_cache.length() > _curr_length :

		if _is_playing == false:
			_is_playing = true
			
		if(_countdown > 0):
			_countdown -=  SOMETHING
		else:
			_curr_length += 1
			dialog.text = _play_cache.left(_curr_length)
			_countdown =  SOMETHING
		pass
	else:
		if _is_playing :
			_play_cache = ""
			_is_playing = false
			_curr_length = 0
			_show_choices()

I think I’d invert it here if I’m understanding it correctly.

Have a variable that tells you how long it’s been since the last time a character was displayed. Every _process, increment that by delta. And then check if it’s passed whatever the character timer is.

And then all you have to do is set two variables, one of them for the faster display, the other for the slower display. And you know it’s been that long when the counter passes that amount.

Sample code:

func _process(delta: float) -> void:
	if Input.is_action_just_pressed("ui_accept"):
		if _is_playing:
			_currspeed = text_faster
		else :
			_forward()
	if Input.is_action_just_released(("ui_accept")):
		_currspeed = text_speed
	
	if _play_cache.length() > _curr_length :

		if _is_playing == false:
			_is_playing = true
			
		if(_counter < _currspeed):
			_counter +=  delta
		else:
			_curr_length += 1
			dialog.text = _play_cache.left(_curr_length)
			_counter =  0
		pass
	else:
		if _is_playing :
			_play_cache = ""
			_is_playing = false
			_curr_length = 0
			_show_choices()
1 Like

I highly recommend using the visible_characters property of your text container with visible_characters_behavior set to “Characters After Shaping”, both RichText and Label support it. This will prevent words from snapping to a new line, work with multiple languages, text effects, and reduce gdscripting memory management on your _play_cache.

_accumulated_text_time += _currspeed * delta
var total_chars_value = _accumulated_text_time * TEXT_PER_SECOND
dialog.visible_characters = total_chars_value
1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.