Show sequential character dialogue with animated portraits and text — triggered by any UnityEvent. Optional decision panel lets players make choices that fire their own events.
Add the component, fill in your lines, and wire a trigger. No Canvas or UI prefab needed — the dialogue system builds its own UI at runtime.
dialogueText, displayTime (seconds on screen), an optional characterImage (Sprite), and orientation (Left or Right). Add as many lines as you need.InputTriggerZone, InputInteractionZone, a button, a key press. Call ActionDialogueSequence → StartDialogue(). To stop mid-sequence, call StopDialogue().displayTime. Recommended for most games — it keeps dialogue from feeling locked in.Each line in the array is a DialogueLine struct. Fill out as many as you need — they play in order from top to bottom.
| Field | Type | Description |
|---|---|---|
| dialogueText | string | The text to display. Supports TextMeshPro rich text tags like <b>, <color=#…>, etc. |
| displayTime | float | How long (seconds) this line stays on screen after finishing its entrance animation. With click-through enabled, players can advance early. |
| characterImage | Sprite | Portrait image for this line. Leave empty for text-only lines. The previous portrait fades out between lines. |
| orientation | Left / Right | Which side of the screen the portrait appears on. Use Left for the player and Right for NPCs, or alternate per speaker. |
textColor and optionally assign a customFont (TMP_FontAsset). These apply to all lines including decision buttons. Text size, alignment, and position are also adjustable there.| Event | When it fires |
|---|---|
| onDialogueStart | When StartDialogue() is called and playback begins |
| onDialogueComplete | After the last line (and decision, if enabled) finishes |
| onLineChanged | Each time a new line begins — passes the line index (int) |
| onDecisionStart | When the decision panel appears (after last dialogue line) |
The defaults (slide-up portrait, typewriter text) look great without any changes. Adjust if you want a different feel — portrait and text animate independently.
| Field | Default | Description |
|---|---|---|
| imageFadeInDuration | 0.2s | How long portrait entrance animation takes |
| imageFadeOutDuration | 0.2s | How long portrait exit animation takes between lines |
| slideDistance | 500 | Pixels the portrait travels during slide animations |
| charactersPerSecond | 30 | Typewriter speed. 20 = slow and dramatic, 60 = fast |
| textFadeInDuration | 0.2s | Duration for text Fade In or Slide animation |
enableClickThrough is on and the typewriter is still running, the first click completes the current line instantly (shows all text). A second click advances to the next line. This is standard RPG behaviour — players who read fast aren't forced to wait.After the last dialogue line, display a panel of clickable choices. Each choice fires its own UnityEvent — wire them to anything: load a scene, spawn an item, start another dialogue.
choiceText (button label), an optional choiceImage (Sprite shown left of the text), and onChoiceSelected (the UnityEvent to fire when clicked).onChoiceSelected like any UnityEvent — load a new scene, call a method, start a different ActionDialogueSequence, update a flag. After a choice is made, onDialogueComplete also fires.| Field | Default | Description |
|---|---|---|
| enableDecision | false | Show a choice panel after the last line |
| decisionChoices | [ ] | Array of DecisionChoice — each has choiceText, choiceImage, onChoiceSelected |
| decisionPanelPosition | (0, -200) | Center of the decision panel in screen-space pixels |
| decisionButtonSize | (400, 100) | Width × height of each choice button |
| decisionButtonSpacing | 20 | Vertical gap between buttons |
| decisionButtonOpacity | 0.9 | Background opacity of buttons (0 = transparent, 1 = solid) |
| decisionFontSize | 36 | Font size on choice buttons |
| fpController | None | Assign for FP scenes — auto-unlocks cursor during decisions |
| Field | Default | Description |
|---|---|---|
| playOnStart | false | Begin dialogue automatically when the scene starts |
| loop | false | Loop back to line 0 after the last line instead of completing |
| enableClickThrough | false | Let mouse click / any key / gamepad A advance or skip lines |
| Field | Default | Description |
|---|---|---|
| backgroundImage | None | Optional full-screen background sprite (e.g. letterbox bars) |
| backgroundPosition / Size | (0,0) / (1920,1080) | Anchor and dimensions of the background image |
| leftPosition / rightPosition | (-400,-100) / (400,-100) | Screen-space anchor for left and right portraits |
| portraitSize | (300,300) | Width × height of portrait images |
| textPosition / textSize | (0,-300) / (1200,200) | Position and size of the dialogue text box |
| fontSize | 48 | TextMeshPro font size for all dialogue text |
| textAlignment | Left | TMP text alignment (Left, Center, Right, etc.) |
| textColor | White | Color of dialogue and decision text |
| customFont | None | Override the default TMP font with any TMP_FontAsset |
| Method | Description |
|---|---|
| StartDialogue() | Begin the sequence from line 0. Safe to call while already playing — restarts from the beginning. |
| StopDialogue() | Immediately stop playback and hide the canvas. |
| NextDialogue() | Skip the current typewriter or advance to the next line. Same as click-through, callable from code. |
| SetTypewriterSpeed(float) | Change charactersPerSecond at runtime. |
| SetLoop(bool) | Toggle loop mode at runtime. |