Skip to content

Game engine export

Access: left sidebar → Export to game engine.

This exports your whole project as a story graph plus a small, ready-to-use runtime package for the target engine — so the exported story can actually be played inside the engine, not just read as data.

Supported engines

EngineStatusWhat you get
Unreal EngineAvailableA ready-to-drop YarnDraft plugin (C++ runtime + Blueprint player) + story.json + audio assets
Godot 4PausedListed in the export dialog but not selectable. The exporter is written; it is switched back on once its GDScript runtime has been tested inside the Godot editor.
UnityPlannedListed in the export dialog but not selectable. The runtime has not been written yet.

What's included

  • Full story graph — dialogue, choices, conditions, instructions, tasks, clues, puzzles, inventory, timers, triggers, and audio cues, converted into an engine-independent JSON (story.json). This is the single source of truth the runtime plays back.
  • A minimal, working runtime for the chosen engine — a script/plugin that reads story.json and walks the graph the same way the YarnDraft canvas simulator does (branching, conditions, variable changes, inventory, etc.), and exposes simple events/signals your game hooks into.
  • Referenced assets — audio and image files used by the story are copied alongside the export.

Why a runtime, not just data?

A plain data export would still leave you to reimplement branching, conditions, and state tracking by hand in every engine. Instead, each export ships a thin interpreter for its engine, so you can start testing the story in-engine immediately.

How the "plugin" actually works

Not a Marketplace/Asset Store plugin

There is nothing to install beforehand. Every export is self-contained: it generates its own copy of the runtime alongside your story data. You don't need — and can't currently get — a separately versioned, pre-built plugin.

This is a deliberate trade-off, and it's worth understanding what it means day to day:

  • The runtime code (the GDScript file / the C++ plugin sources and Blueprint player) is a fixed template — it does not change between exports of the same YarnDraft version. Only story.json and the copied assets are specific to your project.
  • First export: copy the whole folder into your engine project and set it up once (see per-engine steps below).
  • Later exports (story content changed, nothing else): you only need to drop in the new story.json (and any new assets) — you don't need to redo the plugin setup or, for Unreal, recompile, since the C++ hasn't changed.
  • You would need to redo the setup step if a future YarnDraft update changes the runtime template itself. The exported README.md in each bundle always reflects the runtime version it was generated with.

If you need to hand-modify the generated runtime code for your game (custom hooks, extra signals, etc.), keep in mind that re-copying the plugin folder on a later export will overwrite those changes — treat the generated runtime as a starting point you fork, not as something you re-export over indefinitely.

Godot 4

Paused

Godot is currently greyed out in the export dialog. The description below is what the export produces once it is switched back on — it is kept here because the exporter itself is still in the app and unchanged.

<Project>_Godot/
├── story.json
├── yarndraft_player.gd     ← runtime interpreter (Node script)
├── plugin.cfg
└── README.md
  1. Copy the folder into your Godot project (e.g. res://yarndraft/).
  2. Attach or instantiate YarnDraftPlayer (a Node script), then:
gdscript
var player := YarnDraftPlayer.new()
add_child(player)
player.load_story_from_file("res://yarndraft/story.json")
player.dialogue_line.connect(_on_line)
player.choices_presented.connect(_on_choices)
player.story_finished.connect(_on_finished)
player.start()
# Continue a plain line:
player.advance()
# Pick a presented choice:
player.choose(0)
  1. Other signals available: variable_changed, trigger_fired, audio_cue, inventory_changed, task_changed, clue_discovered.

Unreal Engine

The exporter builds a self-contained project folder, ready to drop straight into an Unreal project:

<Project>_Unreal/
├── Plugins/
│   └── YarnDraft/
│       ├── YarnDraft.uplugin          ← CanContainContent is forced to true
│       ├── Source/YarnDraftRuntime/   ← C++ runtime plugin
│       ├── Source/YarnDraftEditor/    ← editor importer for Entity Data Assets
│       └── Content/
│           ├── BP_YarnDraftPlayer.uasset   ← Blueprint wrapper around the C++ player
│           ├── BPC_YarnDraft.uasset        ← Blueprint component
│           ├── WBP_YarnDraftDialogue.uasset
│           └── WBP_YarnDraftChoiceButton.uasset
└── Content/
    └── YarnDraft/
        ├── story.json              ← the sanitized story graph
        └── assets/                 ← referenced .wav / .mp3 / .ogg audio files

Before story.json is written, the exporter sanitizes every flow's edges: duplicate edges (same source, target, source handle and target handle) are collapsed, and orphaned edges (pointing at a node id that no longer exists) are dropped. Only audio actually referenced by a Dialogue or Audio card gets copied into assets/.

Install (first time)

  1. Copy the folders in. Merge the exported Plugins/YarnDraft/ and Content/YarnDraft/ into your Unreal project's root — next to your project's own .uproject file, Plugins/, and Content/ folders. Don't overwrite your existing Plugins//Content/ folders, just drop the YarnDraft subfolder into each.
  2. Open or convert the project for C++. This is a code plugin (C++), so Unreal needs C++ project files before it can build YarnDraftRuntime and YarnDraftEditor.
    • First try opening the .uproject and accepting Unreal's missing-module rebuild prompt.
    • If Windows says the project has no source code when generating files, open the project in Unreal Editor and create one empty C++ class (Tools → New C++ Class), then close the editor.
    • After that, right-click the .uprojectGenerate Visual Studio project files (Windows), or generate Xcode project files on Mac.
    • You'll need Visual Studio with the "Game development with C++" workload (or Xcode on Mac), since Unreal compiles code plugins from source.
  3. Build the module, either:
    • Open the freshly generated .sln in Visual Studio, set the configuration to Development Editor, and build; or
    • Just double-click the .uproject to open it — Unreal will detect that the YarnDraft modules aren't compiled yet and prompt you to rebuild → click Yes and wait for it to finish.
  4. Open the project and confirm the plugin is active: Edit → Plugins, search "YarnDraft" — it should already be enabled (project plugins are on by default), this is just a sanity check if something doesn't show up.

You only need to repeat steps 2–4 once per project — see How the "plugin" actually works above for what later exports actually require (usually just dropping in the new story.json).

Use it

Drop BP_YarnDraftPlayer into a level for a quick smoke test, add the YarnDraft Dialogue component to an actor for the recommended Blueprint workflow, or drive UYarnDraftStoryPlayer directly from C++:

cpp
UYarnDraftStoryPlayer* Player = NewObject<UYarnDraftStoryPlayer>(this);
Player->OnLine.AddDynamic(this, &AMyActor::HandleLine);
Player->OnChoices.AddDynamic(this, &AMyActor::HandleChoices);
Player->OnAudioCue.AddDynamic(this, &AMyActor::HandleAudioCue);
Player->OnFinished.AddDynamic(this, &AMyActor::HandleFinished);
Player->LoadStoryFromFile(FPaths::ProjectContentDir() / TEXT("YarnDraft/story.json"));
Player->Start();
// Continue a plain line:
Player->Advance();
// Pick a presented choice:
Player->Choose(0);

The YarnDraft Dialogue component can also use the plugin's default WBP_YarnDraftDialogue widget for a simple textbox and choice-button UI. Set Story File Name from the dropdown of Content/YarnDraft/**/*.json files, then set Start Flow Name to choose a named flow from that story file. Leave Start Flow Name empty for the root flow.

For Game Event cards in Blueprint, bind the component's On Game Event event. The Event pin contains the event name, and Params.Values contains key/value parameters such as doorId.

For Inventory cards in Blueprint, bind On Inventory Changed on the YarnDraft Dialogue component. It emits the item EntityId and the current Quantity, which is enough to refresh a simple inventory/journal panel or trigger game logic.

For game saves, call ExportStateJson() on the YarnDraft Dialogue component or UYarnDraftStoryPlayer and store the returned string in your save game. After loading the story again, call ImportStateJson(Json) to restore YarnDraft variables, task states, clue flags, and inventory counts. This does not save the current textbox/choice UI position; your game should restart the intended flow or interaction after loading.

Puzzle outcomes are surfaced the same way as dialogue choices (OnChoices / choices_presented): your game decides the actual result and then calls Choose(index) / choose(index).

Timer nodes with seconds use Unreal's timer manager for real delays. A simple Timer continues after the delay; a timed-choice Timer shows choices and automatically follows the timeout branch when the limit expires. turns and days are exported for your game logic, but the default Unreal runtime treats them as immediate because those time systems are game-specific.

Entity Data Assets

The Unreal plugin also includes an editor-only importer for YarnDraft entities. After copying a fresh export into your project and compiling the plugin:

  1. Open Unreal Editor.
  2. Use Tools → Import YarnDraft Entity Data Assets.
  3. The importer reads Content/YarnDraft/story.json.
  4. It creates or updates assets under /Game/YarnDraft/Entities/{TemplateName}/DA_{EntityLabel}.

Each generated asset is a UYarnDraftEntityDefinition (UPrimaryDataAsset) with Blueprint-readable EntityId, TemplateId, TemplateName, DisplayName, PortraitAssetId, PortraitPath, Color, and Fields. The visible Unreal asset name follows the Data Asset convention (DA_<YarnDraft label>); EntityId remains the stable YarnDraft link. Re-export from YarnDraft, replace Content/YarnDraft/story.json, then run the import again to refresh the Data Assets.

Entity reference lists such as spawnLocations are exported as YarnDraft entity ids. In Unreal Data Assets they appear in ReferenceAssets as direct references to the imported entity Data Assets, so Blueprint/game code can use the resolved Location assets without parsing id strings.

Rich text entity fields are imported as markup strings in Fields. The importer also creates or refreshes /Game/YarnDraft/RichText/DT_YarnDraftRichTextStyles, a Rich Text Block style Data Table with rows for Default, the six color tags, Small / Medium / Large, Bold, Italic, and Important. Assign that Data Table to your Unreal Rich Text Block so YarnDraft tags such as <Important>...</> and <Blue>...</> render with matching styles.

Gameplay tags are written to Config/Tags/YarnDraftTags.ini during export, and the Unreal importer/Live Sync path can refresh that file from Content/YarnDraft/story.json. Restart Unreal Editor after adding new tags so the Gameplay Tags manager reloads them.

If Unreal shows a message about YD_StoryData or Import YarnDraft Story, the project is still running an older YarnDraft plugin copy. Close Unreal, replace the whole Plugins/YarnDraft/ folder with the latest exported one, regenerate project files, rebuild, then use Tools → Import YarnDraft Entity Data Assets.

Choice requirements, effects, and voice-over

A choice edge can optionally carry a requirement, an automatic effect, and a voice-over (set from the edge's choice editor in the flow canvas — see Choices (labeled edges)). Both runtimes honor them automatically:

  • Requirement not met, "hidden": the choice is left out of OnChoices / choices_presented entirely.
  • Requirement not met, "disabled": the choice is still included, but with bEnabled = false (Unreal, on FYarnDraftChoice) / "enabled": false (Godot, in the emitted choice dictionary) — render it greyed out; calling Choose/choose on it is a no-op.
  • Effect: applied automatically the moment Choose(index) / choose(index) is called for that option — no extra Advance()/advance() call needed.
  • Voice-over: Unreal broadcasts OnChoiceVoice(VoicePath); Godot re-uses the existing audio_cue signal with {"audioType": "voice", "assetId": ...}.

Verified, but keep an eye on your engine version

The generated Unreal plugin has been build-tested end to end against UE 5.7 (Visual Studio Build Tools toolchain). Godot exports have only been validated for correct JSON/GDScript structure, never run inside the Godot editor — which is why Godot is paused in the export dialog. If you hit an engine-version-specific compile issue, please report it.

YarnDraft — lightweight, cross-platform narrative design tool