Open a dialogue tree that has quietly gone wrong and the shape is always the same: forty or so authored choices, a handful of paths anyone has actually read since the first draft, and a long tail of nodes that exist only because a branch had to end somewhere. That is the branching trap. Choice feels cheap while you are writing it and expensive forever after — every branch has to be written, edited, localised, VO'd if you have VO, wired to state, and tested.
The fix is not "write less dialogue." It is choosing structures that produce the feeling of branching without multiplying the content you owe. Below are the patterns that small teams actually ship with, how to budget nodes before you write a word, and the bookkeeping that keeps a tree readable at month six.
Do the multiplication before you write
Pure branching — where every choice opens a genuinely separate subtree — grows as 2ⁿ. Three binary choices in a row is 8 endings. Five is 32. Eight is 256. No two-person team is writing, editing and localising 256 tails of a conversation, so the tree gets quietly abandoned halfway and the last third of the branches end up as one shared line that reads like a shrug.
Give yourself a node budget instead. A workable rule of thumb for a small team:
- Words per node: 25–60 for spoken lines, 80–150 for a "reading" game
- Nodes per conversation: 12–30 for a normal beat, 60+ only for a set-piece
- Real branch depth: 2, occasionally 3. Beyond that, converge.
Then check the arithmetic against your actual capacity. If your localisation budget is 40,000 words and you have 45 conversations, you have roughly 900 words per conversation across all branches — not per playthrough. That number, decided early, kills more bad structural ideas than any amount of feedback later.
Five structures that buy branching cheaply
1. Hub and spoke
One central node with a list of topics; each spoke is 1–3 nodes and returns to the hub. Spokes get consumed (greyed out) as they're used, and the hub exits when the player picks "That's all" or when a required spoke is done.
Cost is linear: ten topics is ten small units, not 1,024 paths. This is the workhorse for shopkeepers, quest-givers, companions at camp, and any character the player will revisit. Its weakness is pacing — a hub feels like a menu, so use it for information and relationship texture, not for dramatic climaxes.
2. Delayed convergence (the diamond)
Split into 2–3 branches, let them run for 2–4 nodes each, then merge back to a single node that acknowledges which way you came with one varying line. The player remembers the divergence; you only paid for one short middle plus one conditional line.
The trick is what you vary at the merge. Changing what happens is expensive. Changing how the NPC refers to what happened is one line and reads as consequence.
3. Tone-preserving choices
Give the player three options that differ in voice — blunt, warm, evasive — but land on the same next node. This is the pattern behind most "personality" dialogue in shipped RPGs, and it is honest as long as the game never promises those choices change outcomes. Players will forgive a tone choice that doesn't branch. They will not forgive a stated intention that doesn't branch.
Rule: if the option text contains a promise ("I'll bring you the antidote"), the game owes a divergent state. If it contains a manner ("Fine. Whatever."), it owes nothing but a matching reply.
4. State-gated variants instead of branches
Rather than branching the tree, write one path whose individual nodes swap by flag: metPlayerBefore, hasJournal, killedTheDog. Structurally the conversation is a straight line, so it stays testable, but it reads differently on every playthrough. Ten flags checked across a linear tree produce more perceived reactivity than three real branches, at a fraction of the authoring cost.
Keep flags in a single registry with a name, type, who sets it and who reads it. An unregistered flag is a bug waiting for QA week. GameDesignerX's dialogue trees module lets you attach conditions to nodes and see which variables a conversation touches, which is the moment most teams discover they have three flags meaning "the player has been to the mill."
5. The one true branch
Pick one decision per act that genuinely forks and say so in the design doc. Everything else converges. One real fork per act, with visible consequences 20 minutes later, produces a stronger memory of agency than fifteen shallow forks that all resolve inside the same scene.
A budget table you can copy
| Conversation type | Structure | Nodes | Real branches | Flags set |
|---|---|---|---|---|
| Merchant / recurring NPC | Hub and spoke | 12–20 | 0 | 0–1 |
| Quest handoff | Linear + tone choices | 8–14 | 0 | 1–2 |
| Companion beat | Diamond | 15–25 | 2 | 1 |
| Interrogation / puzzle talk | Gated variants | 20–35 | 0 | 3–5 |
| Act climax | One true branch | 25–40 | 2 | 2–3 |
Forty conversations built to this table land around 700 nodes and roughly a dozen genuine forks — a scope a two- or three-person team can actually finish, localise and test.
Bookkeeping that survives month six
Structure is half the problem. The other half is that in six months nobody remembers what node_47b was for.
Name nodes semantically. mara_mill_refuses_bribe beats node_47b. Prefix by character, then scene, then intent. When VO recording day arrives, the filename is the script's index.
Write the exit before the body. Every conversation should state, in one line at the top, what changes when it ends: a flag, an item, a relationship value, a quest step. Conversations with no stated exit condition are the ones that get cut.
Cap the player's option list at four. More than four choices on screen is a menu, not a decision, and it multiplies your test matrix for no felt benefit.
Read every branch aloud once. Silent branches are where placeholder text ships. If you cannot afford to read them all aloud, that is direct evidence the tree is too big.
Track the flag registry next to the tree. One page: flag name, set by, read by, default. Any flag with no reader is dead weight; any flag with three setters is a bug.
Pre-lock checklist
- Every choice that states an intention has a divergent consequence
- Every branch converges within 4 nodes, or is one of the act's declared true forks
- No conversation exceeds the node budget for its type
- Every node has a semantic name and every conversation a stated exit state
- Every flag appears in the registry with at least one reader
- Total word count across all branches fits the localisation budget
- Every reachable path has been read aloud at least once
Cut branches before you cut characters
When dialogue scope has to come down — and it always does — the instinct is to delete characters. Don't. Delete branches first: convert diamonds to tone choices, convert real forks to gated variants, and merge spokes. A cast of eight characters with linear, flag-reactive conversations feels richer than a cast of three with elaborate trees, because players meet breadth constantly and depth only once.
The test for whether a branch has earned its cost is blunt: if a player could not describe the difference this branch made an hour later, it should have been a flag.