Skip to content

Runtime & sequencing

I want a trigger volume or interactable object to start a dialogue

Hold a reference to the placed Dialogue Instance and call StartDialogueInstance on it — that is all a trigger needs. From your trigger volume's overlap event, or your interactable's "use" event, call the instance and the dialogue plays. Selectors and entry-point queries are only for picking which subdialogue runs — you don't need any of that just to launch.

A custom actor exposing a DialogueEntryPoint / instance reference

  1. Place your Dialogue in the level (drop the asset) so you have an ALBRDialogueInstance, and expose a reference to it on your trigger (an instance-editable variable, or a level reference).
  2. From your trigger/interaction event, call StartDialogueInstance on that instance. Done — no flags, no selectors required.
  3. Only if you want designers to pick the dialogue and a selector from the actor's details panel, use the entry-point pattern instead: add a DialogueEntryPoint (FLBRAnyDialogueEntryPoint, instance-editable), implement the LBRHasGPTagMeta interface (override GetGPTagRootFilter to return ALBRDialogueInstance::GetSubdialogueSelectorsCategoriesFromAnyEntryPoint(DialogueEntryPoint) so the selector dropdown fills in), and launch with StartDialogueWithAnyEntryPoint — which also accepts a generic Dialogue, not just a placed instance.

Gotcha

If you use the advanced entry-point pattern, never put a breakpoint in GetGPTagRootFilter — the editor calls it while drawing the details panel, so stopping there can freeze the editor and force a hard close. For the simple case there is nothing to watch out for: StartDialogueInstance just plays the instance.

See also: Runtime — starting from Blueprint · Runtime — triggering from your own objects · Getting started

I want one Dialogue to play a different scene depending on the situation

Put the branching logic in each subdialogue's condition, then just start the dialogue normally — Libretto walks the entry subdialogues in order and plays the first whose condition passes. One Dialogue asset can hold many entries (a greeting, a first meeting, a post-quest variant); a condition on each is the cleanest way to say "this one applies when…", and you don't have to encode the choice in the caller.

  1. On each entry subdialogue, set a condition (ULBRDialogueDoneCondition — GPVars, gameplay tags, your own custom check). Order the entries most-specific first: the post-quest variant above the first-meeting variant above the default greeting.
  2. Launch plainly with StartDialogueInstance. Candidates are evaluated in list order and the first one whose condition passes is played — leave a last entry with no condition as the catch-all default. A StartDialogueWithSelector node with its selector tag dropdown

  3. Only if the caller needs to force a particular variant (not the world state), reach for selectors: tag the subdialogues and start with StartDialogueWithSelector / …Selectors / …SelectorQuery / …AnySelector. Selectors and conditions combine — the first subdialogue whose selectors match and whose condition passes wins.

Gotcha

Prefer conditions over deciding the branch in the caller. Selectors are a targeting handle for when the calling code genuinely must pick a variant; putting the situational logic in the subdialogue's condition keeps the branching with the content and reusable across every launch site. If the selector tags on a StartDialogue* node look stale, recompile the Blueprint; and note the old StartDialogue(SubdialogueName) is deprecated.

See also: Conditions · Runtime — starting from Blueprint · Runtime — subdialogue selectors

I want to run some code when a dialogue ends

Pick the callback that matches the scope you need: the End Event pin fires for one specific playthrough, DialogueEndEvent fires on every exit of that instance, and the manager's OnDialogueEnd fires globally. All three receive the ending — use the narrowest one that covers your case.

An event wired to a StartDialogue node's End Event pin

  1. This playthrough only — wire an event to the End Event pin on the StartDialogue* node you called. It fires once, when that call ends.
  2. Every exit of this instance — on the placed Dialogue Instance, use Actor ▸ Add Event ▸ DialogueEndEvent (a multicast delegate on ALBRDialogueInstance). It fires no matter how the dialogue was launched.

    Add Event ▸ DialogueEndEvent on a Dialogue Instance 3. Anywhere in the project — bind the Dialogue Manager's global OnDialogueEnd (ALBRDialogueInstance*, end reason) to react centrally.

Gotcha

The End Event pin only fires for the StartDialogue* call that set it. If the same dialogue is later launched another way — a trigger, another script — that pin is not called. For a callback that survives across launches, use DialogueEndEvent (per instance) or OnDialogueEnd (global) instead.

See also: Runtime — action at the end of a dialogue · Runtime — listing running dialogues

I want the player to skip the current line — or stop the dialogue entirely

Advancing and ending are two different calls: SentenceSkip jumps forward one line, while StopDialogue (or StopAll) ends playback. Wire them to your input; the showcase player already maps a Skip line and a Stop all dialogues action you can copy.

The showcase input actions: Skip Dialogue Line and Stop All Dialogues

  1. Skip forward / back — call SentenceSkip / SentenceSkipBack on the running Dialogue Instance. Guard the input with the manager's CanSkip so you only offer it when there is a valid destination.
  2. Skip a whole beat — set the subdialogue flag SkipAsWhole (TAG_LBRSubDialogueFlag_SkipAsWhole): in that subdialogue a skip jumps to the next subdialogue instead of the next sentence — handy for skippable intros you don't want stepped through line by line.
  3. Stop a running dialogue — call one of the Dialogue Manager helpers with an end reason: StopDialogue (one instance), StopDialogueInstancesForDialogue (every instance of an asset), StopDialogueInstancesInvolving (every instance with a given character), or StopAll.

Gotcha

Stopping is not skipping. StopDialogue ends the dialogue — like the priority Interrupt outcome, side effects that had not fired yet (GPFlags raised on later lines, line actions) will not run. SentenceSkip only fast-forwards within the same dialogue, so its lines still play out their effects. The showcase wires both on ALBRShowcasePlayer (SkipDialogueLine / StopAllDialogues input actions) if you want a working reference.

See also: Runtime — stopping a dialogue · Priorities — ignored & interrupted dialogues

Two dialogues collide — I want to control which one wins

Give each dialogue a priority level and let the priority system resolve the pair; by default the lower-index (more important) one interrupts, the other is ignored. You only tune this when two dialogues can genuinely overlap — a bark firing during a staged scene, for instance.

  1. Make sure your priority levels are registered and ordered in Project Settings ▸ Libretto ▸ DialoguePriorities — index 0 is the most important.
  2. For the pairs that need special handling, author the outcome in the priority editor (EWBP_LBRDialoguePriorities), per context (who is present). Leave the rest to the default index-order behaviour.
  3. Pick outcomes that actually take effect today (see the gotcha): Interrupt, Pause or Ignore.

Gotcha

Muffle / Mute / PlayMuffled / PlayMuted currently behave like Play for sound. They set the runtime flag and compute a volume modifier, but the base plugin can't apply it (the engine-side audio-filter hook is unavailable), so the affected dialogue keeps playing at full volume. For reliable priority behaviour today, stick to Interrupt, Pause or Ignore.

See also: Priorities — full reference · Priorities — default behaviour

I want to play a dialogue with no placed instance (voicemail, comms, a scene spawned on the fly)

Generate the Dialogue straight from the asset (no instance), then start it with a StartGenericDialogue* function plus a spawn transform — Libretto spawns the Dialogue Instance for you. A generic dialogue is simply one that plays without a pre-placed ALBRDialogueInstance; a voice-over is one use, but it can just as well carry staged characters and animation spawned at the transform you pass.

  1. Generate it from the asset — right-click the Dialogue ▸ Libretto ▸ Generate Sequences… (and Generate Assets… first for audio). Because this path takes no Dialogue Instance, what it produces is a generic dialogue — there is no separate "generate as generic" command.
  2. At runtime call the variant you need, passing the spawn transform: StartGenericDialogue, StartGenericDialogueWithSelector, StartGenericDialogueWithSelectors, or StartGenericDialogueWithSelectorQuery. Each returns the spawned ALBRDialogueInstance.
  3. If you don't know in advance whether you hold a placed instance or a generic Dialogue, use the static StartDialogueWithAnyEntryPoint — it accepts either.

Gotcha

Generic is about how it is launched (spawned from the asset vs. a placed instance), not about whether it has bodies: staged characters, cameras and animation work in a generic dialogue too. Do make sure the characters it needs are actually in the level when it runs, since a generic launch brings no placed instance to carry level references.

Generic dialogues aren't cooked into a packaged build by default

Because a generic dialogue has no placed instance in any map, nothing in the cooked levels references it — so the cooker never reaches it and it (together with its generated sequences) is left out of the package. It plays fine in the editor and in PIE, but in a shipped build the launch silently does nothing. Fix it by cooking the folder explicitly: Project Settings ▸ Packaging ▸ Additional Asset Directories to Cook (a.k.a. Directories to always package) — add the content directory that holds the generic Dialogue and its generated sequences, then repackage.

Play the voice in 2D (voicemail / intercom)

A voicemail, intercom or radio comm usually wants the voice to play flat in 2D, not spatialized somewhere in the world. Two ways to get that:

  • Tick Libretto.Flags.Subdialogue.Staging.Audio2D on the subdialogue — every line it contains is then placed on a root (unbound) audio track and played in 2D, whatever the staging.
  • Or give the lines to an intangible character — it has no body binding, so its voice plays in 2D by default, whatever the subdialogue's flags.

See also: Runtime — generic dialogues · Intangible characters · A voicemail with its transcription in a phone UI