dialogue data format for mid-size games — resource files, JSON, or just use Ink/Yarn?

216 views 10 replies

Working on a narrative-adjacent game in Godot 4, not a visual novel, but probably 60+ branching conversations by the time I ship. I keep second-guessing my data format choice and I'm at the point where switching is still possible but won't be for much longer.

Currently using custom Godot Resources (.tres files). A DialogueLine resource has the speaker, text, conditions, and an array of next-line IDs. A DialogueGraph groups them. It felt smart at first: everything's typed, no parsing step, autocomplete works. The reality is that editing in the Inspector is miserable. Branching means manually managing integer IDs with zero visibility into the graph structure. I have 40 conversations and I already dread touching the old ones.

I looked hard at Yarn Spinner and Ink. Yarn has a proper Godot add-on now and the authoring syntax is genuinely nice. Ink is more mature and Inkle has a track record. But both mean learning a DSL and maintaining an external toolchain on top of everything else. Solo project, so that context-switch cost is real.

JSON is the obvious middle ground: any editor, readable diffs, two lines to parse. But I lose type safety and conditions become unvalidated strings. A typo in a flag name fails silently at runtime, and I will absolutely write that typo at 2am and spend an hour wondering why the quest didn't trigger.

The part I can't figure out: does this decision actually compound at 200 conversations, or does any reasonable approach hold if you have discipline about it? I keep reading takes from people who shipped dialogue-heavy games and they're all using completely different things and none of them seem to regret it.

What format are you actually using for branching dialogue, and did the choice age well?

Replying to TurboThorn: YAML sounds great until you spend 45 minutes debugging why your branching struct...

lmao the Norway problem is the one i bring up every time someone suggests YAML at work and it gets funnier the more you explain it — "yes, a country code is a boolean, it's in the spec, enjoy." the look on people's faces is worth it.

but honestly the silent indentation collapse is what kills me more in practice. at least the Norway thing throws a type error sometimes. wrong indentation level just makes your branching structure disappear into a string and you have no idea until runtime. TOML fixes both of these and i genuinely don't know why it hasn't eaten more of YAML's lunch by now.

mind blown slow motion

we shipped a game using Ink and i'd do it again, but there's one thing nobody warns you about: Ink is great for writers and kind of terrible for reviewing structure. the syntax reads well line by line but getting a birds-eye view of a complex branch is rough. ended up building a small JSON export visualizer just so we could sanity-check that we hadn't written ourselves into dead ends.

at that point i started wondering if we'd have been better off with JSON from the start and slightly better custom tooling. for 60+ conversations i'd still lean Ink, the writer experience is genuinely good, but budget time for visualization tooling if anyone on your team needs to see the full structure at once.

programming adding tools to fix other tools

One thing nobody's mentioned: YAML as a middle ground between JSON and full DSL. It's more readable than JSON for branching structures: no brace noise, multiline strings work, inline lists are clean. A non-technical writer can pick it up faster than Ink syntax or a visual node graph.

Used it on a small narrative side project and had a writer editing files directly after a 15-minute walkthrough. The tradeoffs are the same as any flat-file approach (no type safety, diffs get noisy past a certain size), but as a bridge between "too technical" and "requires learning a new tool" it's underrated. My rough ceiling was around 50 conversations before the lack of visual structure started hurting navigation.

Replying to GlitchLeap: One angle that hasn't come up: if the person writing dialogue isn't comfortable ...

the sheets approach is underrated and i've seen it work well, but the sync step is where it quietly falls apart if nobody explicitly owns it. you're either manually exporting to CSV after every writer change, or you build a proper import pipeline, and suddenly you've spent more time on tooling than on dialogue. if the writer is even a little comfortable with git, Yarn Spinner's graph view is probably less total friction. if they're genuinely not, sheets works, just make sure someone specific is responsible for the export step rather than "we'll figure it out when we need it."

Replying to IronGale: we shipped a game using Ink and i'd do it again, but there's one thing nobody wa...

the structure reviewing problem is exactly what pushed me to try Yarn Spinner and the graph view there is a pretty big deal for that reason specifically. being able to see node connections visually makes it way easier to audit "wait, can the player actually reach this branch" without mentally tracing every path. ink's purity as a text format is genuinely great for diffs and writer-friendly syntax, but for anything with a lot of convergence points you're basically reading a choose your own adventure by hand to trace the flow.

we shipped a small narrative game in Godot 4 using custom Resource subclasses for dialogue and it held up well to about 80 conversations. basically a DialogueNode resource with typed fields for speaker, text, a choices array, and a next-node reference. stays in .tres files, version control is fine, you get inspector editing for free.

the thing that pushed me toward Yarn Spinner on my next project wasn't the data format, it was the editing experience. writers don't want to touch .tres files in a code editor. if it's just you doing the writing, resource files are honestly great. the moment anyone else needs to author dialogue, get a proper tool.

One angle that hasn't come up: if the person writing dialogue isn't comfortable with code or graph editors, a Google Sheet with a defined schema can work as a writer-friendly intermediate layer. Writer fills out rows (id, speaker, text, conditions, next_id), a build script pulls via the Sheets API and bakes to whatever format the game actually loads. We did this on a project where the narrative designer wasn't touching the engine at all, and the iteration speed was genuinely good. She could edit text, reorder conversations, and flag broken branches in a format she already knew.

The failure mode is when branching gets deep enough that a flat table stops representing it cleanly. Past maybe 3 levels of nesting, row-based dialogue starts requiring a lot of mental overhead to follow. At that point Ink is probably the right call. But for straightforward branching with a non-technical writer, the spreadsheet approach is underrated.

Replying to StormLattice: One thing nobody's mentioned: YAML as a middle ground between JSON and full DSL....

YAML sounds great until you spend 45 minutes debugging why your branching structure silently collapsed into a string because of one wrong indentation level. or you hit the Norway problem where NO parses as a boolean in certain parsers and your dialogue key for the "north" option just disappears quietly with zero error.

i really wanted to like YAML for this. the error messages when something goes wrong are some of the least helpful i've encountered in any data format.

man staring at computer completely defeated

One thing the thread hasn't touched on: schema migration. Whatever format you pick, your dialogue structure will change mid-project. A new field for speaker portrait. A localization key. A "skip if flag set" condition you didn't plan for. Multiply that across 60+ conversations and you're in real pain unless you anticipated it.

Custom Resource subclasses in Godot handle this best in my experience. Adding a new exported property with a default just works, old files load without breaking. JSON and YAML both require an explicit migration pass every time the schema changes, which is fine if you actually write one. Whatever you choose, put a schema version field in from day one even if you never increment it. Future you will be grateful.

tbh the format question is mostly a "who's writing dialogue" question more than a technical one. if it's just you in the editor, custom Resource subclasses in Godot are great. fast iteration, type-safe, no extra deps. but the second a non-dev needs to touch it you're gonna end up with Yarn anyway. found this out after building a whole bespoke system, then a writer friend wanted to contribute, spent like 20 minutes trying to add nodes in the Godot editor, and noped out completely lmao. Yarn Spinner's graph view alone is worth the dependency if there's any chance of collaboration.

nope walking away

Moonjump
Forum Search Shader Sandbox
Sign In Register