Roblox NPC dialogue box with typewriter text and branching choice buttons

How to Add a Dialogue System to Your Roblox Game

Dialogue systems bring NPCs to life. A guard who warns you about danger ahead, a merchant who haggles over prices, a mysterious figure who hints at hidden lore — these interactions create the stories players remember. Building a dialogue system that supports typewriter text, branching choices, conditional logic, and quest integration requires careful architecture. This guide walks through a complete, reusable system from data structure to UI rendering.

Architecture: Data-Driven Dialogue

The most maintainable dialogue system separates dialogue content from dialogue logic. Store all dialogue in a data structure — a ModuleScript table or JSON file — that defines dialogue nodes, their text, available choices, and transition rules. The dialogue engine reads this data and drives the UI. A dialogue node contains: an ID, the speaker name, the text to display, an optional array of choices (each with display text and a target node ID), and optional conditions (only show this node if the player has completed quest X). This data-driven approach means writers can add and modify dialogue without touching any rendering or game logic code.

  • Each dialogue node: { id, speaker, text, choices?, condition?, action? }
  • Choices: { text, nextNodeId, condition? } — each choice links to another node
  • Conditions: functions that check player state (quest progress, inventory, flags)
  • Actions: functions triggered when a node is displayed (give item, start quest, set flag)
  • Store dialogue data in ModuleScripts under ReplicatedStorage for client access

Triggering Dialogue: Proximity Prompts

Use Roblox's ProximityPrompt to let players interact with NPCs. Attach a ProximityPrompt to the NPC's HumanoidRootPart or Head. Set the ActionText to "Talk," the MaxActivationDistance to 8-10 studs, and the KeyboardKeyCode to E. When the prompt fires its Triggered signal, open the dialogue UI and start playing the NPC's dialogue tree from its root node. Disable the ProximityPrompt while dialogue is active to prevent re-triggering. Also disable player movement during dialogue by setting Humanoid.WalkSpeed to 0 and locking the camera, then restore both when the conversation ends. For multiplayer, each player has their own dialogue state — one player talking to an NPC does not affect other players.

The Typewriter Text Effect

Typewriter text — revealing characters one at a time — is the standard for game dialogue and dramatically improves readability compared to showing a wall of text instantly. Implement it by starting with an empty TextLabel, then appending one character at a time with a short delay (0.03-0.05 seconds per character). Use RichText formatting by enabling RichText on the TextLabel and wrapping the remaining (untyped) text in a transparent color tag so the TextLabel's text layout does not shift as characters reveal. The trick: set the full text immediately but make untyped characters invisible. This way, the TextLabel computes the correct layout from the start, and characters reveal in place without the text reflowing. Play a soft tick sound every 2-3 characters for audio feedback. Let the player click or press a key to instantly reveal all remaining text in the current node — never force players to wait for slow text they have already read.

  • Set the full text with RichText: visible portion + <font transparency="1">hidden portion</font>
  • Advance the visible boundary by 1 character every 0.03-0.05 seconds
  • Play a subtle tick sound every 2-3 characters for typewriter audio
  • Allow click or key press to instantly reveal all text
  • Pause slightly longer on punctuation (periods: 0.15s, commas: 0.08s) for natural pacing

Branching Choices and Conditional Dialogue

Branching makes dialogue interactive. When a node has choices, display them as buttons below the dialogue text after the typewriter finishes. Each choice links to a different next node, creating a tree structure. For conditional branches, attach a condition function to each choice — only show the choice if the condition returns true. Example: a "I have the artifact" choice only appears if the player's inventory contains the artifact item. For NPC reactions that vary based on player state, use conditional nodes: the root node checks conditions and routes to different text based on quest progress. A player who has defeated the boss sees "You have proven yourself, warrior" while one who has not sees "The beast still lives. Are you not strong enough?" Store player dialogue flags in their save data so conversations persist across sessions.

Quest Integration and Actions

Dialogue is the primary interface for quest systems. Each dialogue node can trigger an action when displayed — give an item, start a quest, advance a quest stage, set a global flag, or open a shop. Actions run on the server via RemoteEvents. The dialogue UI on the client sends the node ID and NPC ID to the server, which validates the interaction (is the player close enough to this NPC, is this node reachable in the dialogue tree) and executes the action. Never grant items or advance quest state from the client. For quest-giving dialogue, use a pattern like: intro text node, branching choice (accept quest / decline), accept routes to an action node that calls the quest service and displays "Quest accepted" text, decline routes to a dismissal node. Track accepted quests in the player's save data and use conditions to show appropriate dialogue on return visits.

Dialogue UI Polish

A polished dialogue box has: a semi-transparent background frame with UICorner and UIStroke, the speaker name in a bold TextLabel above the text, the dialogue text in a readable font size (18-22 on desktop, scale up for mobile), choice buttons below with hover effects, and a "continue" indicator (a small bouncing arrow) that appears when the typewriter finishes and there are no choices. Animate the dialogue box opening with a TweenService scale-up from 90% to 100% over 0.2 seconds with EasingStyle.Back for a subtle pop-in effect. Position the box in the lower third of the screen and add letterbox-style darkening on the top and bottom to focus attention on the text. Optionally, show the NPC's portrait as an ImageLabel on the left side of the dialogue box for character identity.

Frequently Asked Questions

How do I make NPCs talk in Roblox?

Attach a ProximityPrompt to the NPC model. When triggered, open a dialogue ScreenGui on the client and display text from a dialogue data table. Use a typewriter effect to reveal text character by character. The dialogue data can include branching choices that lead to different conversation paths.

How do I make a typewriter text effect in Roblox?

Use RichText to set the full text with untyped characters wrapped in a transparent font tag. Advance the visible boundary by one character every 0.03-0.05 seconds in a loop. This approach keeps text layout stable as characters reveal. Allow the player to click to skip to full text.

How do I make branching dialogue in Roblox?

Store dialogue as a tree of nodes in a ModuleScript. Each node has text and an optional array of choices. Each choice has display text, a target node ID, and an optional condition. When the player picks a choice, navigate to the linked node. Conditions let you show or hide choices based on player state.

Should dialogue logic run on the client or server?

The dialogue UI and text display run on the client. Any actions triggered by dialogue (giving items, starting quests, setting flags) must run on the server via RemoteEvents. The server should validate that the player is near the NPC and that the requested dialogue action is legitimate before executing it.

Looking for assets? Browse the library →