Skip to content

Writing dialogue

The player should pick their answers — how do I branch the conversation?

Add a Choice line, then put Reply lines under it. Each Reply is one option the player can pick; whatever you write under a Reply is the branch that plays when it is chosen. When the branch finishes, reading resumes at the line immediately after the Choice.

A Choice line with Reply options, among other line types

  1. Add a Choice line where the player should decide. Set its Time (seconds allowed to choose; 0 = no time limit).
  2. Add a Reply line under it for each option, and write its branch (Text lines, GoTo, more Choices…) indented beneath it. The Reply's own text is used to display the option to the player; it is not voiced. To voice a player choice, put a Text line spoken by the player character inside the Choice or after it.
  3. To send a branch somewhere other than the line after the Choice, end it with a GoTo (to a line ID/Label, or Next Subdialogue).
  4. Fine-tune each Reply in the details panel: Do Once (once picked, it can no longer be chosen again), Default Reply (picked if the timer runs out), Display Condition (hide it entirely when false), Availability Condition (show it greyed-out and unselectable when false).

Gotcha

After a Reply block ends, the next line played is the one immediately after the Choice, at the same indentation — plan a line for the branches to reconverge on, or use GoTo to route elsewhere.

See also: Dialogue Editor — line types · Choice widgets · Conditions

How do I split a long conversation, or change it depending on context?

Split it into subdialogues. A subdialogue is a self-contained branch of the same Dialogue that you can request by name and gate with a condition — the natural way to hold different conversations between the same characters (before/after a reveal, one-on-one vs. a third character joining) or just to keep a long script readable.

The subdialogue list with several named subdialogues

  1. Add a subdialogue and give it a unique Name.
  2. Optionally set its Selectors (tags to pick or group it) and its Condition (whether it may play at all).
  3. Request a specific subdialogue by name at runtime; on entry, candidates are evaluated in list order and the first one whose name matches and whose condition passes is played.
  4. To chain subdialogues, end one with a GoTo ▸ Next Subdialogue (or a GoTo to a specific line).

Gotcha

The end of a subdialogue is the end of the whole Dialogue unless you jump out with an explicit GoTo — and the order of subdialogues in the list matters, because Next Subdialogue uses it. The character list is shared across the whole Dialogue, but each subdialogue can redefine its own staging (see Stages).

See also: Dialogue Editor — subdialogues · Conditions · Priorities

How do I make a line appear only in certain situations?

Attach a condition. Conditions are small Blueprints that read dynamic game state and return true/false; you can put one on a Reply, on an If/ElseIf/Else branch, or on a whole subdialogue.

A Reply's Display and Availability Condition slots in the details panel

  1. For a player option, use the Reply's Display Condition (hidden when false) or Availability Condition (shown but greyed-out when false).
  2. To branch without player input, use an If / ElseIf / Else block and set the branch's Success Condition — the first branch whose condition is true is entered.
  3. To enable/disable an entire subdialogue, set its Condition.

Gotcha

To test "has this dialogue or subdialogue already been played", use the dedicated ULBRDialogueDoneCondition rather than hand-writing a GPVar-path check — Libretto already records play counts against each dialogue's dynamic tag.

See also: Conditions · GPVars · Dialogue Editor — conditions

How do I run game logic when a line plays?

Attach an action to the line. An action is a Blueprint (ULBRAction) whose DoAction runs when that line plays in-game — a general-purpose hook to give an item, fire a gameplay event, push UI, and so on.

A line carrying an Action and its Blueprint

  1. Select the line and add an Action in its details panel.
  2. Pick or create a subclass of ULBRAction.
  3. Implement DoAction (what happens at play time) and, optionally, GetLabel (a readable label shown on the line in the editor).

Gotcha

Actions are available on every line type except Cinematic and Comment. They run at play time, not at generation — don't rely on them to change what gets generated.

See also: Dialogue Editor — actions · Runtime

How do I give lines to a voice with no body — a phone call, a narrator?

Use an intangible character. Derive it from ULBRIntangibleCharacter and add it to the dialogue like any other character. It has no mesh and no actor in the level, so there is nothing to place or spawn — it only speaks.

An intangible character Blueprint's class defaults

  1. Create a Blueprint from ULBRIntangibleCharacter (no C++ needed).
  2. Set its CharacterName (localized).
  3. Add it in the Dialogue Editor's character list and write its Text lines.

Gotcha

Because it has no body, animation, lip-sync and camera tracks are skipped for it — only its audio and subtitles are produced. (The CharacterGender property only feeds a TTS voice fallback and can generally be ignored.)

See also: Intangible characters · Voices

How do I use a dialogue for a document or on-screen text instead of a played scene?

Tick Staging.Interface2D on its subdialogues and read it from your UI with the reading helpers — this has its own page now. A document, a phone thread, a popup, a voicemail or a lock screen are all covered, with a working example on the tutorial map: see I want to show a dialogue in a UI instead of playing it and, for pages, I want a document or a letter with several pages.

See also: Reading dialogues in 2D interfaces

How do I control exactly what the subtitle shows?

Subtitles are automatic — every played line becomes on-screen text (Speaker : line) with no setup. To change what shows, you tune the shipped widget, swap in your own, use per-line flags, or route subtitles into your existing HUD.

Per-line subtitle flags (NoSubtitle / Subtitle3D)

  1. Make your own from the shipped widget. Rather than editing ULBRSimpleSubtitleWidget in the plugin (which would fight future updates), duplicate/subclass it into your project and tune your copy — toggle bShowSpeakerName, set FontSize, override the look — then point the setting below at it.
  2. Swap the widget at Project Settings ▸ Libretto ▸ UI ▸ Widget Subtitle Class — any class that implements the LBRDialogueSubtitle interface.
  3. Override per line with flags: NoSubtitle (the line plays with no subtitle) and Subtitle3D (rendered in world space above the speaker's head, bark-style).
  4. Use your own HUD by binding the manager delegates OnSubtitleDisplayed / OnSubtitleHidden on ULBRDialogueManager instead of letting Libretto spawn a widget.

Gotcha

Binding OnSubtitleDisplayed takes priority over the built-in widget — once bound, the manager stops spawning WidgetSubtitleClass, so route the subtitles yourself. Subtitle3D needs the speaker's actor to be present in the world; if it can't be resolved (e.g. a bark from an absent character), nothing is shown and no error is raised.

See also: Subtitles · Choice widgets

The editor flags my words as misspelled — how do I fix it, or teach it new words?

The Dialogue Editor runs the Windows spell checker; a line with a mistake turns red and offers suggestions. For legitimate words it doesn't know — proper nouns, acronyms, invented terms — you add them once to a per-project dictionary and it stops flagging them everywhere.

A misspelled line with suggestions

  1. Read the flag. When a line contains an unknown word it turns red; the checker proposes the closest spellings from its dictionaries so you can correct the text in place.
  2. Teach it a word. For a word that is correct but unknown (a character name, an acronym…), add it to the per-project dictionary at Resources/Libretto/personalDictionary.dic — one entry per line. It is then accepted across every dialogue in the project.
  3. Check a whole dialogue at once from Dialogue Tools ▸ Launch CheckSpeller rather than waiting to visit each line.
  4. Tune when it runs in Editor Preferences ▸ Dialogue Editor: bLaunchCheckSpellerAtModification (check a line as you type it, on by default) and bLaunchCheckSpellerAtStart (sweep the whole dialogue when it opens, off by default).

Gotcha

The checker validates against the Windows language matching the editing culture (en → en-US, fr → fr-FR); no dictionary ships with the plugin. For a culture Windows does not have, nothing is flagged and the Output Log warns once (No Windows spell checker for language…). To support another language, add it in Windows Settings ▸ Time & language ▸ Language & region and restart the editor. Lean on personalDictionary.dic for everything project-specific rather than trying to silence individual lines.

See also: Dialogue Editor — Spell checking · Settings — Spell checker