Caution
This is Yarn Spinner for Godot (GDScript) Early Access 3.2. There will be bugs, we might change the API or features with an update, or something may break. We do not recommend you use this to ship a game just yet.
Yarn Spinner for Godot (GDScript) is a pure-GDScript implementation of the Yarn Spinner dialogue system for the Godot engine. It runs compiled Yarn programs and aims for full feature parity with Yarn Spinner for Unity 3.2, including node groups, saliency, detours, smart variables, localisation, and voice over support.
Requires Godot 4.6 or later (not the .NET/Mono version).
Important
Yarn Spinner for Godot (GDScript) is not yet for sale (it will always be available here for free, too). We rely on your support to keep everything free and accessible. If you want to support us during Early Access, you can support us on GitHub Sponsors or Patreon. GitHub sponsors of $25 and above, and Patreon members of the "Scribe" or above tier will receive a license to the paid version when it is released.
Visit the documentation and Yarn Spinner site for more information.
Tip
Please submit issues or feature requests via this form during Early Access: http://yarnspinner.dev/pre-release-feedback
The samples live in their own project in the YarnSpinner-Godot-Samples repository.
The samples project ships without this addon: copy this repository's addons/yarn_spinner/ folder into the samples project's addons/ directory first (the samples README has step-by-step instructions), then open the project in Godot 4.6+, open the scene for the sample you want, and run it with "Run Current Scene" (F6).
The intention is that Yarn Spinner for Godot (C#) and Godot (GDScript) will ship with a full suite of samples on par with the samples supplied as part of Yarn Spinner for Unity.
Yarn Spinner for Godot (C#) is a port of Yarn Spinner for Unity that uses the core Yarn Spinner C# library directly.
It requires the .NET-enabled build of Godot, a .csproj/.sln, and compiles Yarn scripts inside the editor via a C# import plugin.
This GDScript version is a complete reimplementation of the Yarn Spinner runtime in pure GDScript, with no .NET dependency, no DLLs, no C# project needed. It works with the standard (non-.NET) Godot editor and export templates, making it accessible to GDScript-only projects.
Yarn scripts are compiled with the Yarn Spinner compiler bundled with the addon (with ysc as a fallback), and both versions produce identical runtime behaviour from the same .yarn source files.
The VM, protobuf parser, library, and markup system were all written to match Unity's behaviour, and the runtime is checked against Yarn Spinner's own test plans, but there are some differences:
- CLDR plural rules --
[plural]and[ordinal]use the same CLDR plural rules as Yarn Spinner, for every locale it supports. - Culture -- Unity formats the results of
string(),number(),bool()andformat()using the player's current culture. This implementation always uses the invariant culture, sostring(3.5)is3.5on every device. - Extra built-in functions -- As well as Yarn Spinner's built-in functions, this implementation provides
abs,clamp,lerp,inverse_lerp,smoothstep,pow,sqrt,sign,wrap,mod,length,uppercase,lowercase,first_letter_caps,pluralandordinal. Unity doesn't have these, so scripts that call them won't run there unless you register matching functions. - Async model -- Unity uses C#
async/awaitwithYarnTaskandCancellationTokenSourcechains. This implementation uses Godot signals andawaitwith a simplerYarnCancellationToken. The behaviour is largely the same, but the presenter API signatures are different (signals instead of tasks). - Command discovery -- Unity uses
[YarnCommand]and[YarnFunction]attributes on methods. This implementation uses a naming convention (_yarn_command_<name>and_yarn_function_<name>), registering methods fromclass_namescripts when the dialogue runner starts, and from the rest of the scene tree once the scene is ready. When you export your game, the plugin records which scripts declare these methods, so the exported game doesn't need to search for them. - Error handling -- Unity throws exceptions for invalid states (missing variables, bad option indices, etc.). This implementation reports them with
push_error, and stops the dialogue when it can't safely continue. - Markup rendering -- The built-in line presenter renders
[b],[i],[u],[s],[code],[style]and palette markers as BBCode. In Unity these are rendered by TextMesh Pro. - Execution limits -- The virtual machine can optionally stop runaway scripts with
max_instructions_per_stepandmax_call_stack_depth. Both are off by default; Unity has no equivalent. - Localisation -- Unity has multiple line provider backends (built-in, Unity Localization package, Addressables). This implementation uses Godot's
TranslationServerdirectly, with the text, asset and fallback locales set on the line provider.
This project uses the Yarn Spinner Public License. You're free to use it in your own projects, commercial or otherwise. The only restrictions are around redistributing it as part of a competing dialogue tool, and using it to train AI models. Full details are in LICENSE.md. For a plain-language summary of the license terms and the intent behind its use, see the YSPL FAQ.
The addon is the addons/yarn_spinner/ folder inside this repository. That folder is the only part that goes into your project; the rest of the repository (tests, compiler sources, this file) stays behind.
- Clone or download this repository.
- Copy
addons/yarn_spinner/into your Godot project'saddons/directory, or symlink it from your checkout. The result should beres://addons/yarn_spinner/plugin.cfgin your project. - In the Godot editor, go to Project > Project Settings > Plugins and enable Yarn Spinner.
- Drop your
.yarnprojectand.yarnfiles into your Godot project. The plugin compiles them automatically on import using its bundled compiler -- any time a.yarnfile or the.yarnprojectchanges, Godot reimports and recompiles. No separate install is needed. - Only if the bundled compiler isn't available for your platform: install
ysc(the Yarn Spinner Console tool) as a fallback withdotnet tool install YarnSpinner.Console --global --version 3.2.2. - Assign the imported
.yarnprojectto a Dialogue Runner in your scene.
If Godot reports missing dependencies on res://addons/yarn_spinner/... paths, or scripts fail to parse with Could not find type "YarnDialogueRunner", the addon isn't at the path the project expects. The usual cause is copying the whole repository into addons/, which puts the addon at addons/YarnSpinner-Godot-GDScript/addons/yarn_spinner. Move the inner yarn_spinner folder so it sits directly under addons/, then reload the project.
The Yarn Spinner compiler (bundled with the addon, or ysc) compiles .yarn scripts into a binary protobuf program. This plugin reads that binary at import time, parses it into an in-memory program representation, and executes it in a stack-based virtual machine. The VM handles control flow, variable storage, function calls, and content delivery. A dialogue runner orchestrates the VM and routes lines, options, and commands to presenter nodes in your scene tree.
You write dialogue in Yarn, and the plugin compiles and runs it. Compilation happens automatically when Godot imports the .yarnproject file, using the compiler binary bundled with the addon (or ysc from your PATH as a fallback).
The plugin has three layers:
Core (addons/yarn_spinner/core/) contains the rntime engine. The protobuf parser reads compiled .yarnproject binaries. The virtual machine executes instructions. The yarn library provides built-in functions and operators. Variable storage holds game state. The line provider resolves localised text and applies markup. The saliency system selects content when multiple candidates match
Dialogue Runner (addons/yarn_spinner/dialogue_runner.gd) is the main node you add to your scene. It owns the VM, discovers commands from your scene tree, coordinates presenters, and exposes signals for dialogue lifecycle events. All configuration is done through its exported properties in the inspector.
Presenters (addons/yarn_spinner/ui/) display content to the player. The line presenter shows dialogue text with typewriter effects. The options presenter shows choice buttons. The voice over presenter plays audio files synced to lines. You can subclass YarnDialoguePresenter to build your own.
The central node. Add it to your scene, assign a .yarnproject, an call start_dialogue(). Key properties:
yarn_project-- the compiled Yarn project to runstart_node-- which node to begin from (default:"Start")auto_start-- start dialogue when the scene loadsvariable_storage-- where game state is stored (auto-created if not set)saliency_strategy-- how to pick between competing content candidatesshow_selected_option_as_line-- re-display the chosen option as a line of dialogueauto_discover_commands-- find_yarn_command_*methods in your scene automatically
Signals: dialogue_started, dialogue_completed, dialogue_cancelled, node_started, node_completed, command_unhandled, command_received.
Displays a line of dialogue with optional typewriter animation (letter-by-letter or word-by-word). Expects a RichTextLabel for text and an optional Label for character names. Shows a continue indicator when the line is fully revealed.
Shows dialogue choices as buttons. Creates a button per option, handles keyboard and mouse selection, and can hide or disable unavailable options.
Base class for custom presenters. Override run_line() to handle lines and run_options() to handle choices. Multiple presenters can be active at once -- the runner coordinates them.
Base class for game state storage. The built-in YarnInMemoryVariableStorage stores variables in a dictionary. Subclass it to save to disk or sync with your game systems. Supports typed access (get_float, get_bool, get_string) and change subscriptions with automatic cleanup.
Define commands in your scripts by naming methods _yarn_command_<name>. The runner discovers them automatically. Return a Signal to make the runner wait for it before continuing.
func _yarn_command_shake(intensity: float) -> void:
# called from Yarn: <<shake 2.5>>
pass
func _yarn_command_fade(duration: float) -> Signal:
# async: runner waits for the signal
var tween = create_tween()
tween.tween_property(self, "modulate:a", 0.0, duration)
return tween.finishedLocalisation uses Godot's TranslationServer. Export your Yarn strings to CSV, translate them, and import them through Godot's standard localisation workflow (Project Settings > Localization > Translations). Set the translation_prefix on the dialogue runner to control the key prefix (default: "YARN_").