SpeechBubbleController extends DialogueController to create positioned speech bubbles with directional arrows and avatar support. Perfect for in-game character dialogue, NPC conversations, or tutorial hints.

Features

  • Arrow Positioning: Directional arrows (top/bottom, left/right)
  • Avatar Support: Left and right avatar positions with breathing animations
  • Position Control: Set bubble position via code
  • Input Integration: Continue button and input action support
  • Next Icon Animation: Animated indicator when text completes

Inheritance

UIViewComponent → DialogueController → SpeechBubbleController

Basic Usage

csharp
using UnityEngine; using CupkekGames.Luna; public class NPCDialogue : MonoBehaviour { [SerializeField] private SpeechBubbleController _speechBubble; [SerializeField] private Sprite _npcAvatar; private void Start() { _speechBubble.OnContinue += OnPlayerContinue; _speechBubble.OnTextComplete += OnTextComplete; } public void StartDialogue() { // Show speech with avatar and arrow pointing to character _speechBubble.Continue( "Hello adventurer! Welcome to our village.", avatarLeft: _npcAvatar, avatarRight: null, arrowPosition: SpeechBubbleArrowPosition.BottomLeft, skipCurrent: false ); } private void OnTextComplete() { _speechBubble.ShowNext(); } private void OnPlayerContinue() { _speechBubble.HideNext(); // Load next dialogue line... } }

Arrow Positions

PositionDescription
NoneNo arrow displayed
BottomLeftArrow points down-left
BottomRightArrow points down-right
TopLeftArrow points up-left
TopRightArrow points up-right
csharp
// Point arrow toward speaker location _speechBubble.SetArrowPosition(SpeechBubbleArrowPosition.BottomLeft);

Properties

AutoShowNext

Gets or sets whether the next icon automatically shows when text completes.

csharp
_speechBubble.AutoShowNext = true; // Default

Methods

Continue (Extended)

Extended version with avatar and arrow support.

csharp
public bool Continue( string text, Sprite avatarLeft, Sprite avatarRight, SpeechBubbleArrowPosition arrowPosition, bool skipCurrent )
ParameterDescription
textThe dialogue text (supports text effects)
avatarLeftSprite for left avatar (null to hide)
avatarRightSprite for right avatar (null to hide)
arrowPositionDirection of the speech bubble arrow
skipCurrentWhether to skip currently playing text

SetPosition

Sets the speech bubble position on screen.

csharp
public void SetPostion(Vector2 pos)
csharp
// Position bubble at screen coordinates _speechBubble.SetPostion(new Vector2(400, 300));

SetSpeechBubbleMaxWidth

Sets the maximum width of the speech bubble container.

csharp
public void SetSpeechBubbleMaxWidth(StyleLength maxWidth)
csharp
// Limit bubble width _speechBubble.SetSpeechBubbleMaxWidth(new StyleLength(400));

SetArrowPosition

Changes the arrow direction.

csharp
public void SetArrowPosition(SpeechBubbleArrowPosition arrowPosition)

Avatar Methods

csharp
// Show avatars with breathing animation public void ShowAvatarLeft(Sprite sprite) public void ShowAvatarRight(Sprite sprite) // Hide avatars public void HideAvatarLeft() public void HideAvatarRight()

Next Icon Methods

csharp
// Show/hide the "continue" indicator public void ShowNext() public void HideNext()

Events

EventInheritedDescription
OnTextStartYesFired when text begins playing
OnTextCompleteYesFired when text finishes
OnContinueNoFired when player presses continue

UXML Structure

xml
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:luna="CupkekGames.Luna"> <ui:VisualElement name="SpeechBubble"> <ui:VisualElement name="AvatarLeftContainer"> <ui:VisualElement name="AvatarLeft" /> </ui:VisualElement> <ui:Label name="Speech" /> <ui:VisualElement name="AvatarRightContainer"> <ui:VisualElement name="AvatarRight" /> </ui:VisualElement> <ui:Button name="ContinueButton" /> <luna:InputPrompt name="NextIcon" /> <ui:VisualElement name="SpeechArrowContainer"> <ui:VisualElement class="bottom_left" /> <ui:VisualElement class="bottom_right" /> <ui:VisualElement class="top_left" /> <ui:VisualElement class="top_right" /> </ui:VisualElement> </ui:VisualElement> </ui:UXML>

Example: Character Conversation

csharp
using System.Collections.Generic; using UnityEngine; using CupkekGames.Luna; public class CharacterConversation : MonoBehaviour { [SerializeField] private SpeechBubbleController _speechBubble; [SerializeField] private Sprite _heroAvatar; [SerializeField] private Sprite _villagerAvatar; private Queue<DialogueLine> _dialogueQueue = new(); private void Start() { _speechBubble.OnContinue += NextLine; _speechBubble.OnTextComplete += () => _speechBubble.ShowNext(); // Queue up conversation _dialogueQueue.Enqueue(new DialogueLine( "Excuse me, have you seen any monsters around here?", _heroAvatar, null, SpeechBubbleArrowPosition.BottomRight )); _dialogueQueue.Enqueue(new DialogueLine( "Monsters? Oh my! They went toward the <shake>dark forest</shake>!", null, _villagerAvatar, SpeechBubbleArrowPosition.BottomLeft )); _dialogueQueue.Enqueue(new DialogueLine( "Thank you! I'll deal with them.", _heroAvatar, null, SpeechBubbleArrowPosition.BottomRight )); NextLine(); } private void NextLine() { _speechBubble.HideNext(); if (_dialogueQueue.Count > 0) { var line = _dialogueQueue.Dequeue(); _speechBubble.Continue( line.Text, line.LeftAvatar, line.RightAvatar, line.ArrowPosition, false ); } else { // Conversation complete _speechBubble.UIView.FadeOutThenDestroy(); } } private struct DialogueLine { public string Text; public Sprite LeftAvatar; public Sprite RightAvatar; public SpeechBubbleArrowPosition ArrowPosition; public DialogueLine(string text, Sprite left, Sprite right, SpeechBubbleArrowPosition arrow) { Text = text; LeftAvatar = left; RightAvatar = right; ArrowPosition = arrow; } } }

USS Animation Classes

The controller uses these USS classes for animations:

css
/* Avatar breathing animation */ .vn_avatar_anim { scale: 1.02; transition: scale 0.5s ease-in-out; } /* Next icon bounce animation */ .vn_next_icon_anim { translate: 0 -5px; transition: translate 0.3s ease-in-out; }

Tips

  • Use SetPosition to place bubbles near speaking characters
  • The arrow position should point toward the speaker
  • Avatar animations use TransitionToggleRepeat for smooth breathing effects
  • For world-space positioning, see Coordinate Utilities

Settings

Theme

Light

Contrast

Material

Dark

Dim

Material Dark

System

Sidebar(Light & Contrast only)

Light
Dark

Font Family

DM Sans

Wix

Inclusive Sans

AR One Sans

Direction

LTR
RTL