Building a Node-Based Dialogue System in Unity: A Deep Dive into the Real Implementation
How I built a scalable, visual dialogue system with action integration, ScriptableObjects, and a custom Unity Editor tool.

Building a Node-Based Dialogue System in Unity: A Deep Dive into the Real Implementation
When I first set out to build a dialogue system for my tower defence prototype, I naively thought “hey, getting the dialogue working is probably simple.” For basic text and if statements, it would have been. But I quickly realised that approach wasn’t scalable, and went down a rabbit hole that ended with a sophisticated node-based dialogue system featuring a custom Unity Editor, ScriptableObject architecture, and action integration.
Results at a Glance
- 🚀 Scalable: Tested up to 1000+ nodes and 1000+ connections with stable performance
- 🎨 Visual Workflow: Full Unity Editor window with graph view, minimap, and drag-and-drop connections
- 🔗 Integrated Actions: Dialogue choices can trigger in-game events (quests, shops, scene changes)
- 🧩 Reusable: Designed as a generic tool, usable across multiple Unity projects
- ⚠️ Work in Progress: Not quite production-ready yet, with more features planned

Why Build a Custom Dialogue System?
My initial motivation was simple: I wanted to build a game for fun. While I didn’t have the full game planned out, I knew dialogue would be a part of it, so I thought I’d start coding there while I finished fleshing out the rest of the idea.
I quickly realised if statements weren’t going to work for complex dialogue. I thought some sort of visual node-based system would be easier to read and manage long-term. GraphView seemed to be something built into Unity that fit my criteria for what I wanted to build.
The learning goals emerged as I went along:
- How a visual node editor could be implemented with GraphView
- How to tie dialogue into gameplay actions
- How to structure data for scalability and maintainability
- What it takes to build Unity Editor extensions that feel professional
Core Architecture: ScriptableObjects over JSON
I considered several options for storing dialogue data, but chose ScriptableObjects as the backbone of the system:
- 🔎 Inspector-friendly: Designers can inspect, edit, and reference dialogue directly in the Unity Editor
- 🏗 Native references: Keeps node connections intact without manual ID mapping
- ⚡ Serialization: Built-in support for Unity’s save/load workflows
- 🔧 Extensibility: Easy to add fields (like localisation or conditions) without schema migrations
- 🔗 Unity Integration: ScriptableObjects integrate seamlessly into Unity workflows — loading dialogue is just a matter of using the ScriptableObject directly, rather than parsing JSON
A DSDialogueContainerSO
stores all dialogue groups, and each node is represented by a DSDialogueSO
, keeping things modular and reusable.
GraphView Implementation
Unity’s GraphView API formed the foundation of the editor. I considered alternatives like custom editor windows or JSON-based tools, but GraphView’s built-in panning, zooming, and native Unity feel made it worth the quirks and workarounds:
- Port Management: I had to roll a custom port creation/connection system
- Serialization: Unity doesn’t natively persist GraphView state, so I built a custom save/load utility
- Documentation: The lack of documentation made it difficult to understand the API’s full capabilities
- UI Limitations: GraphView has restrictions like fixed port heights, which required workarounds
Despite its limitations, GraphView gave me the flexibility to design a tool that felt natural inside the Unity Editor.
Action System Integration
From the start, I wanted dialogue to be gameplay-relevant. I envisioned two types of actions: post-choice actions (like opening a shop) and pre-choice triggers (like quest completion that makes certain choices available).
I picked some generic action types that seemed useful across different games: OpenShop
, GiveItem
, TriggerEvent
, etc. As development continues, I might add more actions or even support for multiple actions per choice. There’s also a custom action type for the occasional complex logic that might be needed.
The main challenge was working around GraphView’s height restrictions when fitting action configuration into the small choice node area. This led to the action menu popup system.
I kept the implementation simple: enums work perfectly for dropdowns and are easy to extend. The handler just checks which enum is coming in and calls the appropriate function. I’m planning to make the handler an abstract class so each game can implement its own action logic.
Runtime Dialogue Manager
The DialogueManager handles runtime presentation and interaction. It displays text, speaker names, and dynamically generates player choices. Because dialogue data comes straight from ScriptableObjects, designers can update conversations without touching runtime code.
Performance & Extensibility
The system remained stable even under stress testing. I started with a basic 10-node dialogue and progressively duplicated it to 50, 100, 300, and eventually 1000+ nodes with 1000+ connections. Even at this scale, I could pan, zoom, and interact with the dialogue window without performance issues. To support testing, I also built a custom debug window that reports metrics like node and connection counts.
The modular ScriptableObject design makes it easy to extend. The action handler pattern means adding new functionality is straightforward — just extend the enum and implement the handler logic.
Currently the system has nodes with speech and choices, and choices have actions to trigger something to happen. Future features planned include:
- Group Minimisation: Collapse dialogue groups to reduce visual clutter in the editor
- Localisation: Language-specific ScriptableObjects
- Conditional Dialogue: Show/hide choices based on player state
- Analytics: Track player choice patterns
- Voice Integration: Automated voice line management
Case Study: Tower Defence Prototype
In my tower defence prototype, the system powered character conversations and in-game shops triggered by dialogue choices. This proved the architecture could support branching quests, player progression, and gameplay-relevant dialogue — a strong foundation for more ambitious games.
Lessons Learned
- Editor Tools: Building something that feels native to Unity requires working within GraphView’s quirks
- Data Structures: ScriptableObjects are powerful but need careful reference management
- UX Matters: Designing for non-developers (like my fiancée, who tested it) forced me to think carefully about usability
- Time Investment: Next time, I might consider purchasing a package instead of spending all my time on a dialogue system
Conclusion
What began as a curiosity became a robust, reusable tool that enhances both development workflow and player experience.
For designers and writers, the system offers a visual way to craft branching conversations. For developers, it’s type-safe, extensible, and performant. And for me, it was a deep dive into building editor tools that scale beyond a single project.
💡 Have you built your own dialogue tools in Unity? I’d love to hear about your approaches, challenges, and solutions. Feel free to reach out if you want to discuss Unity editor development or dialogue systems!
If you’re looking for someone who can design scalable Unity tools like this, let’s talk.