← Back to portfolio
Unity Editor Tool · 2D

2D Dialogue System

A complete dialogue and character-direction toolkit with a visual node editor — designed so writers and designers can build rich conversations without writing code.

Unity C# Node Editor 2D
Overview
Conversations that scale with your game

Most dialogue solutions force you to choose: either you hard-code every branch in scripts, or you accept a limited, rigid tool. This system was built to remove that trade-off. Writers and designers work in a visual node graph inside the Unity editor — connecting lines, choices, conditions, and actions — while the runtime handles typing, portraits, branching, and side effects cleanly.

The dialogue layer itself is dimension-independent: it does not care whether your game is 2D or 3D. What is purpose-built for 2D screen space is the companion NPC movement system — paths, facing, door teleports, and sprite animation are designed around a top-down or side-view world and can be driven directly from dialogue nodes.

The result is a production-ready toolkit that has already shipped in real projects: full branching conversations, relationship-driven choices, comic panels, alerts, scene changes, and coordinated character movement — all authored visually and executed reliably at runtime.

Type
Editor Tool + Runtime
Engine
Unity
Language
C#
Focus
2D games
Editor
Node-based
Status
Used in a bachelor's thesis project
Dialogue System
Structure

Conversations are stored as graph assets. Each graph is a set of nodes and the links between them; a runtime component walks the graph, resolves conditions, prints text, and executes commands. No code is required to build or extend a conversation — the graph is the single source of truth.

Six node types cover the full range of authoring needs: a fixed entry node, a text node, a choice node, a command-only node (no text, actions only), a comic-panel node, and an end node. A checkpoint flag can be applied to any node to mark it as a named, revisitable point in the conversation.

Branching and conditions

Links between nodes carry the branching logic. A link can hold any number of conditions, each checking one actor's relationship value against a target number with a comparison operator (greater / less / equal / not equal), combined with normal or inverted logic. A choice is only offered to the player if all of its conditions pass. If no choice on a node passes its conditions, the system logs a warning and advances safely instead of stalling.

Three relationship categories are tracked per actor — a main relation, a help/assistance value, and a secret value — each on a 0–10 scale with persistent storage across sessions.

Actors and presentation

Actors are defined once and reused across every conversation: a display name, a preferred screen side, and a set of mood portraits (neutral, happy, angry, shocked, terrified, dead). Any individual line can hide the actor's name or portrait for a more cinematic or ambiguous delivery.

Dialogue text is revealed with a typewriter effect, skippable by keyboard or mouse unless the node explicitly disables skipping. A node can also be set to auto-advance after a fixed delay, which is useful for cutscenes where no input is expected. Choice buttons are generated automatically from a node's outgoing links and are selectable with number keys as well as the mouse.

Short, disposable lines that do not warrant a full graph — an item pickup reaction, a passing remark — are supported through a lightweight single-line mode that reuses the same actor and text presentation without requiring a conversation asset.

Commands

Any node can carry an ordered list of commands, executed after its text (or immediately, for command-only nodes). Available commands:

• Update a relationship value — add to or set an actor's relation, help, or secret score
• Show an alert, optionally with an icon, queued so multiple alerts never overlap
• Move an actor along a path, optionally waiting for that movement to finish
• Wait for every currently active movement in the scene to finish
• Fade the screen in or out
• Play a sound effect, optionally waiting for it to finish
• Change scene
• Fire a named signal that other systems can subscribe to
• Control a tutorial sequence — start it, advance a step, suspend it, or shut it down

Commands run in sequence; any command that takes time can be marked to block the conversation until it completes, keeping dialogue, movement, and effects synchronized without manual timers.

Checkpoints, suspend/resume, and comic panels

Checkpoint nodes give a conversation a set of named re-entry points, useful for quests resumed later or for iterating during development. Any node can also be flagged to suspend the conversation on arrival: execution freezes in place and can be resumed later from the exact same node, which covers cases such as the player opening a menu or leaving mid-conversation.

Comic-panel nodes are a distinct node type: the screen fades, a full panel image is shown, and the player either skips it or waits for it to auto-continue. Combined with conditions, alerts, and signals, this covers hand-crafted narrative beats without a separate cutscene system.

NPC Path System
Structure

Movement is authored separately from dialogue as reusable path assets, each a sequence of 2D points with per-point wait time and optional speed override. A path can include teleport markers that route a character through a named door, so it can walk up to a doorway, disappear, and reappear on the other side of the scene. On completion, a path can force the character into a final facing direction.

Execution

Two mover variants execute a path. The world variant drives a physics-based character in scene space: it follows the path, plays four-directional walk animation, and emits footstep sounds attenuated by distance to the player. The UI variant instead drives a screen-space element through its anchored position, with no physics body and higher default speeds, intended for portraits and canvas-only movement. In both variants, sufficiently high speed collapses a move into an instant teleport rather than a tween, which is used for snap cuts.

A path is triggered either through a dialogue command — with an option to block the conversation until that specific movement finishes, or until every active movement in the scene finishes — or independently, from any other gameplay system. The same path asset can be reused across multiple conversations or triggered outside of dialogue entirely.

Extensibility
Adapting to a project

The core loop — the node graph plus its runtime — stays fixed, while almost everything around it is designed to be extended without touching that core. New moods are a single enum value plus a sprite. New commands follow one interface, so a new one only requires implementing its logic and adding an entry to the node editor's command menu. New node types follow the same pattern: a flag on the node data, a factory in the editor, and a handling branch in the runtime.

Several parts of the system are effectively pluggable rather than hard-wired to the dialogue core: comic panels are one visual-interrupt implementation and could be swapped for a different cutscene format; NPC movement is a self-contained subsystem that dialogue merely calls into, and could be replaced by a different locomotion system while keeping the same dialogue-side interface; relationship tracking, alerts, signals, and the tutorial hook are each isolated behind their own command, so individual pieces can be extended or dropped independently.

Editor Tools
Dialogue graph editor

Conversations are authored in a dedicated node-based editor window, opened either from the menu or by double-clicking a conversation asset. Nodes are placed through a right-click context menu or toolbar buttons and connected by dragging between ports; port compatibility is checked automatically. Selected nodes can be duplicated in place, and the canvas supports standard zoom, panning, and rectangle selection.

Each node type exposes its own fields directly on the canvas: text nodes show actor, mood, and per-line flags (hide name, hide portrait, disable skip, auto-transition delay); choice nodes expose one port per option with an editable button label; comic nodes reference a comic asset plus optional text; end nodes expose an end delay and fade-out toggle; checkpoint nodes expose an ID and a suspend flag. A missing entry node is created automatically when a graph is opened.

Choice ports have their own inline editor: conditions are added and removed with dedicated buttons, each condition exposing its logic, actor, relationship type, operator, and value as direct fields. Every node also exposes a command list editor — commands can be added from a menu listing all available command types, reordered up or down, and removed individually. Each command type renders its own set of fields; the movement command in particular includes an actor picker and a path selector that filters candidate path assets by folder or by scene/actor match, so the correct path is easy to find without knowing its file name.

The graph autosaves on every change, with a toolbar indicator that turns on for unsaved changes and doubles as a manual save button.

NPC path editor

Paths are edited through a custom inspector combined with an in-scene visualization, in two coordinate modes: world space for normal scene NPCs, and UI space (matched to a canvas) for screen-space cutscene movement. The inspector lists every point with its position, wait time, and speed override, offers a one-click path reversal that also flips any teleports, and lets any point be turned into a teleport with a door and enter/exit type picked from a dropdown.

The scene view draws the full path as connected line segments, with teleport legs shown as dashed lines with directional arrows toward the target door, point markers that turn red when a point overlaps a collider, and draggable handles for repositioning points directly in the scene. Holding a modifier key and clicking on the scene inserts a new point at the cursor. A labeled arrow marks the path's final facing direction, and start/end/index labels are drawn above each point together with the path's name.

An optional ghost preview animates a placeholder character walking the path exactly as it will move at runtime — respecting wait times, speed overrides, and teleports — so timing and pacing can be checked without entering play mode. Segment lengths and collision checks are cached and only recomputed when points change, and the editor supports editing several selected paths at once.

Workflow
Putting it together

1. Define an actor asset for each character — name, screen side, and mood portraits.
2. Build any movement the scene needs as path assets, placing and previewing points in the scene view.
3. Attach a mover component to each NPC and link it to its actor.
4. Open a conversation asset in the graph editor and lay out nodes for the scene.
5. Wire choice conditions where the story should branch on relationships.
6. Attach commands to nodes as needed — relationship changes, alerts, a movement call with wait-to-finish, a scene change, and so on.
7. Trigger the conversation at runtime; the graph, its conditions, and its commands handle the rest without further scripting.

Results & Source
Screenshots, video, code

— placeholder — add a screenshot of the node editor, a gif of a conversation in-game, and a link to the source repository here.