Quick answer: RichTextLabel → bbcode_enabled = true. Set text with the tags. [lb] and [rb] escape literal brackets when you don’t want them parsed. Setting bbcode_enabled after assigning text doesn’t retroactively re-parse — set the flag first.

Game text uses [b]Damage:[/b] 50 for emphasis. RichTextLabel renders it literally with the brackets visible. The bbcode flag is off; turn it on and rewrite text after.

The Symptom

RichTextLabel renders BBCode tags as plain characters. [b]bold[/b] shows as [b]bold[/b] instead of bold. Color, size, and other tags equally inert.

The Fix

Step 1: Enable BBCode. Inspector → RichTextLabel → bbcode_enabled. Tick on. The text re-parses.

Step 2: Set text with tags.

extends RichTextLabel

func _ready() -> void:
    bbcode_enabled = true
    text = "[b]Damage:[/b] [color=red]50[/color]"

Order matters: set bbcode_enabled before text. Setting after means the parser sees the property change but doesn’t re-tokenize until the next text assignment.

Step 3: Escape stray brackets. User-supplied text containing brackets breaks parsing.

func set_safe_text(user_input: String) -> void:
    var safe = user_input.replace("[", "[lb]").replace("]", "[rb]")
    text = "[b]" + safe + "[/b]"

This prevents an attacker (or a user typing brackets into a chat) from injecting their own tags — including ones that load images.

append_text vs text

For incremental updates (a typewriter effect, an event log), use append_text:

append_text("[color=yellow]Quest started[/color]\n")
append_text("Find the [b]ancient key[/b].\n")

append_text appends without re-parsing earlier content. Faster for streaming logs than rebuilding the full text each line.

Custom Effects

Godot supports custom BBCode effects via RichTextEffect resources. Common pre-built effects: shake, wave, tornado. Add to install_effect array on the label, then use:

text = "[shake rate=20.0 level=5][rainbow]CRITICAL HIT[/rainbow][/shake]"

Verifying

Run the scene. Bold text should be bold. Colored text colored. If still raw, the flag is off; if mostly working but stray brackets break the layout, escape user input.

“Flag on, then text. Escape user input. append_text for streams.”

Related Issues

For Label autosizing, see Control anchors. For UI font issues, see font size theme.

Enable, set, escape. The text comes alive.