All pages
Powered by GitBook
1 of 2

Loading...

Loading...

Unreal Quickstart

Learn how to get started with Yarn Spinner in Unreal Engine 5.

This is a Pre-release of Yarn Spinner for Unreal Engine. 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.

Please submit issues or feature requests via this form during the pre-release period:

This gets you from zero to running dialogue in about five minutes. It assumes you already know how to write Yarn and use Unreal Engine.

Yarn Spinner for Unreal Engine 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 the Pre-release period, you can support us on or . 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.

Install the Plugin

Visit https://github.com/YarnSpinnerTool/YarnSpinner-UnrealEngine to download the plugin. Then:

  1. Copy the YarnSpinner/ plugin folder into your Unreal project's Plugins/ directory.

  2. Open your project in the Unreal Editor -- the plugin will be detected automatically.

Install ysc

The plugin needs ysc (the Yarn Spinner Cosole) to compile your .yarn files. Install the required version of it globally with:

The editor plugin will find ysc automatically if it's on your PATH or in a standard dotnet tools location (~/.dotnet/tools/).

Create a .yarnproject file and your .yarn files. The .yarnproject tells the compiler which .yarn files to include -- the sourceFiles field is a list of globs or specific paths:

This compiles every .yarn file in the project directory and its subdirectories. You can be more specific:

A game can have multiple .yarnproject files, each pointing to different sets of .yarn files. Each one compiles independently into its own program -- useful for separating main story dialogue, NPC barks, tutorials, etc. Each project becomes its own UYarnProject asset in Unreal.

Drag your .yarnproject file and .yarn files into the Content Browser. The editor plugin automatically runs ysc compile on it, which compiles all .yarn files in the project's sourceFiles scope into a single binary program, string table, and metadata CSV. The plugin parses those outputs and creates a UYarnProject asset. The temp files are cleaned up automatically.

Compilation is always the full set of source files as defined by the project -- there's no incremental or per-file compilation.

The editor plugin watches your .yarn files on disk. When you save a change to any .yarn file (or the .yarnproject itself), the corresponding UYarnProject asset is automatically reimported -- no manual action needed. Adding a new .yarn file that matches the project's sourceFiles globs also triggers automatic reimport. Rapid saves are debounced into a single reimport.

You can also reimport manually by right-clicking the asset in the Content Browser and selecting Reimport.

Here's the minimal setup:

  1. Create an actor in your level (or use an existing one).

  2. Add a UYarnDialogueRunner component. In the Details panel, set Yarn Project to your imported Yarn project asset.

  3. Add a UYarnDialoguePresenter component

Call StartDialogue on the dialogue runner component:

Other dialogue control nodes available in Blueprints:

  • Start Dialogue -- begin from a specific node name

  • Start Dialogue From Start -- begin from the configured StartNode

  • Stop Dialogue -- stop immediately

  • Is Dialogue Running

Or tick bAutoStart in the Detals panel and set StartNode to your starting node name -- dialogue begins automatically when the game starts.

That's it. Run the game and your dialogue plays.

Commands let Yarn tell your game to do things.

The easiest way to handle commands in Blueprints is with *Command Handler Objects. Add any Blueprint (or Actor, or UObject) to the dialogue runner's Command Handler Objects array in the Details panel. When Yarn executes a command, the runner looks for a function with the same name on those objects.

For example, if your Yarn script has:

Create a Blueprint with functions named play_sound and shake_camera. Parameters are automatically converted from strings -- FString, float, int, bool, FVector, FRotator, etc. all work:

  1. Create a new Blueprint (any UObject subclass)

  2. Add a function named play_sound with an FString parameter

  3. Add a function named shake_camera with a float parameter

The runner auto-discovers functions matching command names. No string parsing required.

You can also bind to the OnUnhandledCommand event on the dialogue runner. It fires with the full command text whenever a command isn't handled by any registered handler -- useful as a catch-all.

The runner handles these commands automatically:

  • <<wait 2.0>> -- pause dialogue for a duration (in seconds)

  • <<stop>> -- end dialogue immediately

Functions let Yarn read values from your game. Register them in C++ with a name, implementation, and parameter count:

Use them in Yarn expressions:

Yarn variables work out of the box. Declare them in your .yarn files and they're stored in an in-memory variable storage:

The UYarnBlueprintLibrary provides static functions for reading and writing variables. All are available in the Blueprint action menu under Yarn Spinner | Variables:

Reading variables:

  • Get Variable As Number -- get a float variable (returns false if not found or wrong type)

  • Get Variable As String -- get a string variable (works for any type, converts automatically)

  • Get Variable As Bool -- get a bool variable (returns false if not found or wrong type)

  • Has Variable -- check if a variable exists in storage

Writing variables:

  • Set Number Variable -- set a float variable

  • Set String Variable -- set a string variable

  • Set Bool Variable -- set a bool variable

All of these take a Dialogue Runner reference and the variable name (with $ prefix):

Inspecting project defaults:

  • Get All Declared Variable Names -- get all variables declared in a Yarn project

  • Get Declared Variable Default Value -- get the initial value of a declared variable

The runner creates a UYarnInMemoryVariableStorage automatically if you don't assign one. If you need persistence, implement the IYarnVariableStorage interface and assign it in the Details panel.

The in-memory variable storage supports change listeners. Register a callback that fires whenever a specific variable changes:

These are BlueprintCallable on UYarnInMemoryVariableStorage. Access the storage from the runner's VariableStorage property.

The plugin provides one-call save/load functions that persist all Yarn variables to disk using Unreal's USaveGame system. Available in Blueprints under Yarn Spinner | Persistence:

  • Save Variables To Slot -- save all variables to a named save slot

  • Load Variables From Slot -- load variables from a save slot (clears existing variables first)

  • Does Variable Slot Exist -- check if a save slot exists

  • Delete Variable Slot -- delete a save slot from disk

The default slot name is "YarnVariables" and the default user index is 0. Use different slot names for multiple save slots (e.g., "YarnSave_Slot1", "YarnSave_Slot2").

All three variable types (float, string, bool) are serialised. The save file is written to Unreal's standard save game directory (Saved/SaveGames/).

The dialogue runner fires events at key points during dialogue execution. Bind to these in Blueprints by dragging off the dialogue runner component and selecting the event:

  • On Dialogue Start -- dialogue has begun

  • On Dialogue Complete -- dialogue has ended

  • On Node Start (NodeName) -- a node has started executing

  • On Node Complete (NodeName) -- a node has finished executing

Options Presenter:

  • On Option Selected (OptionIndex) -- player picked an option

  • On Options Display Complete -- options finished fading in

  • On Options Dismissed -- options finished fading out

Voice Over Presenter:

  • On Voice Over Started -- audio playback began

  • On Voice Over Complete -- audio playback finished

Variable Storage:

  • On Variable Changed (VariableName, NewValue) -- any variable was modified

You can change which Yarn project a dialogue runner uses at runtime. This is useful for level transitions, DLC content, or modding support.

In Blueprints:

From C++:

SetYarnProject handles all the internal state:

  • Stops any active dialogue

  • Updates the VM to use the new program

  • Updates the line provider for localisation

  • Updates variable storage's initial value lookups

Existing variables in storage are preserved -- only the project's initial value lookups change. After swapping, call StartDialogue to begin running from the new project.

The UYarnBlueprintLibrary class provides static functions accessible from any Blueprint. Find them in the action menu under Yarn Spinner.

Query information about a Yarn project asset:

  • Get All Node Names -- list all nodes in a project

  • Has Node -- check if a node exists

  • Get Node Count / Get Line Count -- project statistics

  • Get All Line IDs -- list all dialogue line IDs

  • Get Dialogue Runner (Actor) -- find the runner component on an actor

  • Get All Dialogue Runners (WorldContext) -- find every runner in the level

Pure functions for creating and converting FYarnValue structs:

  • Make Yarn Value From String/Number/Bool -- create values

  • Yarn Value To String -- convert any value to a display string

  • Get Yarn Value Type Name -- get the type name ("String", "Number", "Bool")

On UYarnDialogueRunner in the Details panel:

  • Yarn Project -- the imported Yarn project asset to run

  • Start Node -- which Yarn node to begin from (default: "Start")

  • Auto Start -- begin dialogue when the game starts

On UYarnDialoguePresenter:

  • Auto Advance -- automatically continue to the next line after a delay

  • Auto Advance Min/Max Delay -- timing bounds for auto-advance

  • Auto Advance Time Per Character -- extra delay per character in the line

On UYarnWidgetPresenter:

  • Typewriter Speed -- characters per second (0 = instant)

  • Background Color / Text Color / Character Name Color -- appearance

  • Widget Class -- custom UMG widget class to use

On UYarnOptionsPresenter:

  • Option Widget Class -- the widget Blueprint to use for each option button

  • Show Unavailable Options -- show options the player can't pick (greyed out) instead of hiding them

  • Strikethrough Unavailable -- draw a strikethrough on greyed-out options

  • Show Last Line -- display the last line of dialogue above the options

On UYarnVoiceOverPresenter:

  • End Line When Voice Over Complete -- auto-advance when audio finishes

  • Fade Out Time On Interrupt -- fade-out duration when interrupted

  • Wait Time Before Start / Wait Time After Complete -- pre/post audio delays

  • Audio Component -- the audio component to play through

If the built-in presenters don't fit your UI, subclass UYarnDialoguePresenter.

  1. Create a new Blueprint with UYarnDialoguePresenter as the parent class.

  2. Override Run Line -- this receives the localised line with character name, text, and markup. Display it however you like, then call On Line Presentation Complete when done.

  3. Override Run Options -- this receives the option set. Display the options, then call On Option Selected with the chosen index.

The FYarnLocalizedLine struct passed to RunLine contains:

  • Text -- the final localised text

  • CharacterName -- extracted character name (from "Name: text" format)

  • TextWithoutCharacterName -- text with the character name prefix removed

Register it the same way: add it to the DialoguePresenters array on the dialogue runner.

Subclass UYarnOptionWidget to customise option button appearance. Override these Blueprint events:

  • Setup Option -- initialise the widget with option data and index

  • Set Option Unavailable -- style the widget as unavailable

  • On Option Selected -- the option was highlighted/focused

  • On Option Deselected -- the option lost focus

The widget has OptionText (UTextBlock) and OptionButton (UButton) as bound widgets. Add them to your UMG widget and the base class wires them up.

If you're using node groups (multiple versions of the same content with when: conditions), set a saliency strategy on the runner in the Details panel. Available strategies:

  • First -- pick the first viable candidate

  • Best -- pick the most specific (highest complexity) viable candidate

  • BestLeastRecentlyViewed -- pick the most specific candidate that hasn't been seen recently

  • RandomBestLeastRecentlyViewed -- like above, but randomised among equally-good candidates (this is the default)

The built-in line provider (UYarnBuiltinLineProvider) supports full localisation. Key properties (all configurable in Details panel or from Blueprints):

  • Auto Detect Culture -- automatically use the system's locale

  • Text Locale Code -- manually set the locale (e.g., "fr", "de", "ja")

  • Use Fallback -- fall back to another locale if a translation is missing

Blueprint functions on the line provider:

  • Get Locale Code -- get the current locale

  • Set Locale Code -- change the locale at runtime

  • Get Available Locales -- list all locales that have translations

  • Add Localized String -- add a runtime localised string for a line ID and locale

Add a UYarnVoiceOverPresenter component to play audio synced to dialogue lines. It looks up USoundBase assets by line ID and plays them through a UAudioComponent. Configure the base content path and it handles the rest -- fade-in, fade-out, and interruption are all built in.

Override GetVoiceOverClip in a Blueprint subclass to customise how audio assets are resolved.

Add a UYarnDebugHUDComponent to your actor to get a real-time debug overlay showing:

  • Current node and line ID

  • All variables and their values

  • Execution history (lines, options selected, commands, node transitions)

Configure in the Details panel:

  • Dialogue Runner -- which runner to monitor

  • Toggle Key -- key to show/hide the HUD (default: F3)

  • Show By Default -- whether to show the HUD on start

  • Auto Log Events -- automatically log dialogue events to the history

You can also use the UYarnDebugWidget directly in your own UMG layouts.

The plugin supports Yarn's full markup system. Tags in your dialogue text are parsed and made available to presenters:

Register custom markup processors by implementing the IYarnMarkupProcessor interface, or use the built-in UYarnPaletteMarkupProcessor with a UYarnRichTextPalette data asset to define styles in the editor without writing code.

(or a subclass like
UYarnWidgetPresenter
). This handles displaying lines of dialogue. Create a UMG widget for your dialogue UI and assign it.
  • Add a UYarnOptionsPresenter component. This handles showing dialogue choices. Create an option widget blueprint using UYarnOptionWidget as the base class, and assign it to OptionWidgetClass.

  • Wire the presenters to the runner. In the Details panel on the UYarnDialogueRunner, add your presenter components to the DialoguePresenters array.

  • -- check if dialogue is active
  • Continue -- advance to the next content

  • Request Hurry Up -- speed up presentation (e.g., complete typewriter instantly)

  • Request Next Line -- skip the current line entirely

  • Select Option -- pick an option by index

  • Get Current Node Name -- get the name of the executing node

  • Set Yarn Project -- swap to a different Yarn project at runtime (see Runtime Project Swap)

  • Add that Blueprint to the runner's Command Handler Objects array

  • Get All Variable Names -- get an array of all variable names currently in storage

  • Get All Variables -- get a map of all variables and their values

  • On Unhandled Command (CommandText) -- a command wasn't handled by any registered handler

    Resets presentation state

    Get Node Tags -- get tags for a specific node

  • Get All Declared Variable Names -- list all declared variables

  • Get Declared Variable Default Value -- get a variable's initial value

  • Run Selected Option As Line
    -- after the player picks an option, show it as a line of dialogue before continuing
  • Saliency Strategy -- how to pick between competing content candidates (First, Best, BestLeastRecentlyViewed, RandomBestLeastRecentlyViewed)

  • Verbose Logging -- log all VM execution to the output log for debugging

  • Command Handler Objects -- array of objects with functions that match command names

  • Use Fade Effect -- fade the options panel in/out

  • Fade In/Out Duration -- timing for fade effects

  • Enable Keyboard Navigation -- navigate options with arrow keys/WASD and confirm with Enter/Space

  • Navigate Up/Down Key -- configurable navigation keys (defaults: Up/Down arrows, W/S)

  • Confirm Key -- configurable confirm key (defaults: Enter, Space)

  • Optionally override On Dialogue Started, On Dialogue Complete, On Node Enter, On Node Exit, On Hurry Up Requested, On Next Line Requested, and On Prepare For Lines.

    Metadata -- array of line tags (from #tag syntax in Yarn)

  • TextMarkup -- parsed markup attributes for effects like [bold], [shake], etc.

  • RawLine -- the original line data including LineID and substitutions

  • Fallback Locale Code -- the fallback locale (default: base language)

    Screen Anchor -- position on screen (0,0 = top-left, 1,1 = bottom-right)

    Add Your Yarn Files

    Import Into Unreal

    Set Up the Actor

    Start Dialogue

    From Blueprints

    From C++

    Commands

    Blueprint Command Handling

    C++ Lambda Registration

    Built-In Commands

    Functions

    Variables

    From Blueprints

    From C++

    Variable Change Listeners

    Save and Load Variables

    Events

    From C++

    Additional Events on Other Components

    Runtime Project Swap

    Blueprint Utility Functions

    Project Inspection

    Finding Dialogue Runners

    Value Conversion

    Useful Settings

    Custom Presenters

    In Blueprints

    In C++

    Custom Option Widgets

    Node Groups and Saliency

    Localisation

    Voice Over

    Debug HUD

    Markup

    https://yarnspinner.dev/pre-release-feedback
    GitHub Sponsors
    Patreon
    dotnet tool install YarnSpinner.Console --global --version 3.1.0-alpha1
    {
      "projectFileVersion": 3,
      "sourceFiles": ["**/*.yarn"],
      "baseLanguage": "en"
    }
    {
      "sourceFiles": ["Dialogue/*.yarn", "Barks/*.yarn"]
    }
    Dialogue Runner -> Start Dialogue ("Start")
    UYarnDialogueRunner* Runner = MyActor->FindComponentByClass<UYarnDialogueRunner>();
    Runner->StartDialogue(TEXT("Start"));
    <<play_sound "boom">>
    <<shake_camera 2.5>>
    DialogueRunner->AddCommandHandler(TEXT("shake"), [this](const TArray<FString>& Params)
    {
        float Intensity = FCString::Atof(*Params[0]);
        CameraShake(Intensity);
    });
    
    DialogueRunner->AddCommandHandler(TEXT("fade"), [this](const TArray<FString>& Params)
    {
        float Duration = FCString::Atof(*Params[0]);
        FadeToBlack(Duration);
    });
    DialogueRunner->AddFunction(TEXT("player_health"), [this](const TArray<FYarnValue>& Params) -> FYarnValue
    {
        return FYarnValue(Player->GetHealth());
    }, 0);
    
    DialogueRunner->AddFunction(TEXT("has_item"), [this](const TArray<FYarnValue>& Params) -> FYarnValue
    {
        FString ItemName = Params[0].ConvertToString();
        return FYarnValue(Inventory->HasItem(ItemName));
    }, 1);
    <<if player_health() < 50>>
        You're not looking so good.
    <<endif>>
    
    <<if has_item("key")>>
        The door opens.
    <<endif>>
    
    You have {format("{0:F0}", player_health())} health remaining.
    <<declare $coins = 0>>
    <<declare $player_name = "Adventurer">>
    <<declare $has_sword = false>>
    
    <<set $coins = $coins + 50>>
    Welcome, {$player_name}! You have {$coins} coins.
    Get Variable As Number (Dialogue Runner, "$coins") -> OutValue, ReturnValue
    Set Number Variable (Dialogue Runner, "$coins", 100.0)
    FYarnValue Coins;
    if (DialogueRunner->GetVariableStorage()->TryGetValue(TEXT("$coins"), Coins))
    {
        float CoinCount = Coins.ConvertToNumber();
    }
    
    DialogueRunner->GetVariableStorage()->SetValue(TEXT("$player_name"), FYarnValue(TEXT("Hero")));
    Add Number Change Listener (Storage, "$coins", OnCoinsChanged)
    Add String Change Listener (Storage, "$player_name", OnNameChanged)
    Add Bool Change Listener (Storage, "$has_sword", OnSwordChanged)
    Remove Change Listener (Handle)
    Save Variables To Slot (Dialogue Runner, "YarnVariables", 0) -> bool
    Load Variables From Slot (Dialogue Runner, "YarnVariables", 0) -> bool
    DialogueRunner->OnDialogueStart.AddDynamic(this, &AMyActor::OnDialogueStarted);
    DialogueRunner->OnDialogueComplete.AddDynamic(this, &AMyActor::OnDialogueEnded);
    DialogueRunner->OnNodeStart.AddDynamic(this, &AMyActor::OnNodeEntered);
    DialogueRunner->OnNodeComplete.AddDynamic(this, &AMyActor::OnNodeExited);
    DialogueRunner->OnUnhandledCommand.AddDynamic(this, &AMyActor::OnCommand);
    Dialogue Runner -> Set Yarn Project (NewYarnProject)
    Runner->SetYarnProject(NewProject);
    UCLASS(Blueprintable)
    class UMyPresenter : public UYarnDialoguePresenter
    {
        GENERATED_BODY()
    
    public:
        virtual void RunLine_Implementation(const FYarnLocalizedLine& Line, bool bCanHurry) override
        {
            // Display the line however you want
            UE_LOG(LogTemp, Log, TEXT("%s: %s"), *Line.CharacterName, *Line.Text);
    
            // Call this when you're done presenting the line
            OnLinePresentationComplete();
        }
    
        virtual void RunOptions_Implementation(const FYarnOptionSet& Options) override
        {
            // Build your own UI, then call OnOptionSelected(index) when the player picks one
            for (int32 i = 0; i < Options.Options.Num(); i++)
            {
                UE_LOG(LogTemp, Log, TEXT("  [%d] %s"), i, *Options.Options[i].Line.Text);
            }
        }
    };
    I [bold]really[/bold] need your help with [shake]this[/shake]!
    You need {format("{0:N0}", $coins)} coins.    // thousand separators
    I have [plural value={$apples} one="% apple" other="% apples"/].

    Unreal

    Yarn Spinner for Unreal is in Pre-release now.

    Yarn Spinner for Unreal Engine is a pure-C++ implementation of the Yarn Spinner dialogue system for Unreal Engine. It runs compiled Yarn programs with the goal of full feature parity with Yarn Spinner for Unity, including node groups, saliency, detours, smart variables, localisation, markup, and voice over support.

    The entire plugin is intended to be Blueprint-accessible. You can set up dialogue, handle commands, read/write variables, save/load state, swap projects at runtime, and build custom presenters entirely from Blueprints with no C++ required.

    A sample project will be coming soon, during the pre-release period!

    Requires Unreal Engine 5.4 or later. If you want to use Yarn Spinner for Unreal Engine with an earlier version of Unreal Engine, please contact us via https://yarnspinner.dev

    Yarn Spinner for Unreal Engine 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 the Alpha period, you can support us on or . 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.

    Please submit issues or feature requests via this form during the pre-release period:

    Differences from Yarn Spinner for Unity

    The VM, protobuf parser, library, and markup system were all written to match Unity's behaviour, but there are some differences:

    • CLDR plural rules -- Unity includes the full Unicode CLDR v42.0 database (~150 languages). This implementation has rules covering ~130 languages. Coverage is comprehensive, but if you're using [plural] or [ordinal] markup tags with a some languages, you might get the default "one/other" fallback instead of the correct plural form.

    • No Unicode NFC normalisation -- Unity normalises markup input text to NFC (composed) form before parsing. Unreal doesn't have a built-in NFC normaliser, so precomposed and decomposed Unicode characters are treated as-is. This only matters if your Yarn scripts contain combining characters like e + \u0301 instead of é.

    • Async model -- Unity uses C# async/await with YarnTask and CancellationTokenSource chains. This implementation uses Unreal delegates and a two-tier UYarnCancellationToken system (hurry-up then next-content). The behaviour is the same, but the presenter API uses UE-idiomatic patterns instead of tasks.

    • Command discovery -- Unity uses [YarnCommand] attributes on methods. This implementation uses Blueprint-callable UFUNCTION methods on registered command handler objects, plus a C++ AddCommandHandler API. Both approaches register commands, just with diffeent syntax.

    • Error handling -- Unity throws exceptions for invalid states (missing variables, bad option indices, etc.). This implementation uses UE_LOG warnings/errors and defensive fallbacks where possible, which is more idiomatic for Unreal Engine.

    • Localisation -- Unity has multiple line provider backends (built-in, Unity Localization package, Addressables). This implementation uses Unreal's FText and string table system. You can subclass the line provider to plug in your own localisation pipeline.

    • Blueprint support -- This implementation exposes the full dialogue system to Blueprints. Every component is Blueprintable, every control method is BlueprintCallable, all events are BlueprintAssignable, and presenter methods are BlueprintNativeEvent. A UYarnBlueprintLibrary provides 30+ static utility functions. See Blueprint Support for details.

    • Persistence -- Unity has SaveStateToPersistentStorage/LoadStateFromPersistentStorage. This implementation provides SaveVariablesToSlot/LoadVariablesFromSlot via UYarnBlueprintLibrary, using Unreal's native USaveGame system.

    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.

    1. Copy the YarnSpinner/ folder from this repository into your Unreal project's Plugins/ directory (so that YarnSpinner.uplugin is at Plugins/YarnSpinner/YarnSpinner.uplugin).

    2. Open your project in the Unreal Editor -- the plugin will be detected automatically.

    3. Install ysc

    A game can have multiple .yarnproject files, each with its own sourceFiles scope -- useful for separating story dialogue, NPC barks, tutorials, etc. Each one compiles independently into its own UYarnProject asset.

    The Yarn Spinner compiler (ysc) compiles a .yarnproject and all .yarn files in its sourceFiles scope into a single binary (.yarnc), a string table CSV, and a metadata CSV. The editor plugin runs ysc automatically at import time via a custom UFactory, parses the outputs into an in-memory program representation (UYarnProgram), and cleans up the temp files. At runtime, a stack-based virtual machine executes the program. The VM handles control flow, variable storage, function calls, saliency selection, and content delivery. A dialogue runner component orchestrates the VM and routes lines, options, and commands to presenter components in your scene.

    Compilation is always the full set of source files as defined by the project -- there's no incremental or per-file compilation. The editor plugin watches your .yarn source files on disk and automatically reimports the associated UYarnProject asset when any change is detected -- edits, new files, or changes to the .yarnproject itself. Rapid saves are debounced into a single reimport. You can also reimport manually via right-click in the Content Browser.

    You write dialogue in Yarn, drag in the .yarnproject, and the plugin handles compilation, file watching, and everything else.

    The plugin has three layers:

    Core (Source/YarnSpinner/) contains the runtime engine. The protobuf parser reads compiled .yarnproject binaries. The virtual machine (FYarnVirtualMachine) executes instructions. The built-in library provides operators and functions (arithmetic, comparisons, visited, random_range, format, etc.). Variable storage (IYarnVariableStorage) holds game state. The markup parser applies CLDR plural rules, [select]/[plural]/[ordinal] replacement markers, and the adoption agency algorithm for nested tags. The saliency system selects content when multiple candidates match. The smart variable evaluation VM resolves computed variables.

    Dialogue Runner (UYarnDialogueRunner) is the main component you add to your actor. It owns the VM, registers built-in functions, discovers commands from handler objects, coordinates presenters, and exposes delegates for dialogue lifecycle events (OnDialogueStart, OnNodeStart, OnNodeComplete, OnDialogueComplete, OnUnhandledCommand). All configuration is done through its UPROPERTY fields in the Details panel. Every control method is BlueprintCallable and every event is BlueprintAssignable.

    Presenters display content to the player. UYarnDialoguePresenter is the base class -- it delivers lines with typewriter animation and handles the hurry-up/next-content cancellation flow. UYarnOptionsPresenter shows dialogue choices. UYarnVoiceOverPresenter plays audio files synced to lines. UYarnWidgetPresenter manages UMG widgets for dialogue UI. All presenters are Blueprintable -- subclass them in Blueprints and override RunLine, RunOptions, and other events without writing C++.

    The plugin is designed for Blueprint-first development. Every component, method, and event is accessible from Blueprints.

    Dialogue control -- start, stop, pause, and resume dialogue. Check if dialogue is running. Get the current node name. Swap Yarn projects at runtime.

    Command handling -- add any Blueprint to the runner's CommandHandlerObjects array. Functions matching command names are discovered and called automatically with type-converted parameters. No string parsing needed.

    Variable access -- read and write Yarn variables by name. Get/set typed values (string, float, bool). List all variables. Check if a variable exists. Listen for variable changes with callbacks.

    Save/load -- one-call save and load of all Yarn variables to disk via Unreal's USaveGame system. Manage save slots (check existence, delete).

    Runtime project swap -- change which Yarn project a runner uses at runtime via SetYarnProject. Useful for level transitions, DLC, or modding.

    Custom presenters -- subclass UYarnDialoguePresenter in Blueprints and override RunLine and RunOptions to build custom dialogue UI without any C++.

    Custom option widgets -- subclass UYarnOptionWidget to customise option button appearance. Override SetupOption, SetOptionUnavailable, OnOptionSelected, OnOptionDeselected.

    Event binding -- bind to OnDialogueStart, OnDialogueComplete, OnNodeStart, OnNodeComplete, OnUnhandledCommand, OnVariableChanged, OnOptionSelected, OnVoiceOverStarted, OnVoiceOverComplete.

    Localisation -- change locale at runtime, query available locales, add runtime localised strings.

    Project inspection -- query node names, line IDs, tags, variable declarations, and project statistics from Blueprints.

    Debug overlay -- add a UYarnDebugHUDComponent for a real-time debug display showing variables, execution history, and current dialogue state. Toggle with a configurable key.

    A static function library providing 30+ utility functions accessible from any Blueprint. All functions appear under Yarn Spinner in the action menu.

    Category
    Functions

    The central component. Add it to an actor, assign a Yarn Project asset, and call StartDialogue().

    Configuration properties (all editable in Details panel):

    • YarnProject (BlueprintReadOnly) -- the imported Yarn project asset to run

    • StartNode (BlueprintReadWrite) -- which node to begin from (default: "Start")

    • bAutoStart (BlueprintReadWrite) -- start dialogue when the game begins

    BlueprintCallable methods:

    • SetYarnProject -- swap to a different Yarn project at runtime

    • StartDialogue / StartDialogueFromStart -- begin dialogue

    • StopDialogue -- stop immediately

    BlueprintAssignable events:

    • OnDialogueStart -- dialogue has begun

    • OnDialogueComplete -- dialogue has ended

    • OnNodeStart (NodeName) -- a node started executing

    Base presenter class for displaying dialogue lines. Handles typewriter-style text reveal with configurable speed (letters per second), auto-advance timing, and the two-tier cancellation system (hurry-up reveals text instantly, next-content advances to the next line). Supports character name extraction and markup-processed text.

    BlueprintNativeEvent methods (override in Blueprint subclasses):

    • RunLine (Line, bCanHurry) -- display a line of dialogue. Must call OnLinePresentationComplete when done.

    • RunOptions (Options) -- display dialogue choices. Must call OnOptionSelected(Index) when the player picks one.

    BlueprintCallable methods:

    • OnLinePresentationComplete -- signal that line presentation is done

    • OnOptionSelected (Index) -- signal that an option was chosen

    • SetAutoAdvanceEnabled / IsAutoAdvanceEnabled -- auto-advance control

    BlueprintReadOnly state:

    • bIsPresentingLine / bIsPresentingOptions -- current presentation state

    • CurrentLine / CurrentOptions -- current content being presented

    Ready-to-use text presenter that creates and manages a UMG widget. Handles typewriter effects with configurable speed.

    • TypewriterSpeed (BlueprintReadWrite) -- characters per second (0 = instant)

    • BackgroundColor / TextColor / CharacterNameColor (BlueprintReadWrite) -- appearance

    • WidgetClass

    Shows dialogue choices. Receives an option set from the runner, creates UI for each option, handles selection via mouse/keyboard/gamepad, and reports the selected option back.

    Configuration (all BlueprintReadWrite):

    • OptionWidgetClass -- the option button widget class

    • OptionsContainer -- panel to add option widgets to

    • bShowUnavailableOptions / bStrikethroughUnavailable -- unavailable option display

    BlueprintCallable methods:

    • SelectOptionByIndex / SelectNextOption / SelectPreviousOption -- navigation

    • ConfirmSelectedOption -- confirm selection

    • GetSelectedOptionIndex

    BlueprintAssignable events:

    • OnOptionSelected (OptionIndex)

    • OnOptionsDisplayComplete / OnOptionsDismissed

    Individual option button widget. Subclass in Blueprints to customise appearance.

    BlueprintNativeEvent methods:

    • SetupOption (Option, Index) -- initialise with option data

    • SetOptionUnavailable -- style as unavailable

    • OnOptionSelected / OnOptionDeselected -- focus state

    Bound widgets (add these to your UMG widget):

    • OptionText (UTextBlock, BindWidget)

    • OptionButton (UButton, BindWidget)

    Plays audio files synced to dialogue lines. Looks up audio assets by line ID and plays them through a UAudioComponent. Supports fade-in/fade-out and interruption.

    • bEndLineWhenVoiceOverComplete (BlueprintReadWrite) -- auto-advance on audio end

    • FadeOutTimeOnInterrupt / WaitTimeBeforeStart / WaitTimeAfterComplete (BlueprintReadWrite) -- timing

    • AudioComponent

    Default variable storage. Stores variables in a TMap. Implements the IYarnVariableStorage interface.

    BlueprintCallable methods:

    • SetString / SetNumber / SetBool / SetValue -- set variables (BlueprintNativeEvent)

    • TryGetValue / Contains -- read variables (BlueprintNativeEvent)

    BlueprintAssignable events:

    • OnVariableChanged (VariableName, NewValue)

    Full localisation support. Auto-detects system culture, supports fallback locales.

    • bAutoDetectCulture / TextLocaleCode (BlueprintReadWrite) -- locale configuration

    • bUseFallback / FallbackLocaleCode (BlueprintReadWrite) -- fallback configuration

    • GetLocaleCode

    Debug overlay for monitoring dialogue state at runtime.

    • DialogueRunner (BlueprintReadWrite) -- runner to monitor

    • DebugWidgetClass (BlueprintReadWrite) -- custom debug widget class

    • ToggleKey (BlueprintReadWrite) -- key to show/hide (default: F3)

    Commands can be handled three ways:

    1. Blueprint Command Handler Objects (recommended for Blueprints) -- Add any UObject to the runner's CommandHandlerObjects array. Create functions matching command names. Parameters auto-convert from strings to the function's parameter types (FString, float, int, bool, FVector, FRotator, etc.).

    2. C++ Lambda Registration:

    3. OnUnhandledCommand event -- catch-all for commands not handled by methods 1 or 2. Fires with the full command text string.

    From Yarn:

    Localisation uses the Yarn Spinner compiler's CSV string table export. The compiler generates a -Lines.csv file containing all line IDs and their text. Translate the CSV, reimport, and the plugin resolves localised text at runtime through the line provider. The built-in line provider supports auto-detection of system culture, manual locale override, and fallback locales -- all configurable from Blueprints at runtime.

    The UYarnVoiceOverPresenter component plays audio assets matched to dialogue line IDs. Place your audio files in a content directory structure that maps to line IDs, configure the presenter with the base path, and it will automatically find and play the right audio for each line. Supports USoundBase assets (wav, ogg, etc.). Override GetVoiceOverClip in a Blueprint subclass for custom audio resolution.

    (the
    tool) from : dotnet tool install YarnSpinner.Console --global --version 3.1.0-alpha1
  • Write your dialogue in .yarn files. Create a .yarnproject file that defines which .yarn files to include via sourceFiles globs.

  • Drag your .yarnproject into the Content Browser. The plugin automatically runs ysc compile, parses the compiled program, string table, and metadata, and creates a UYarnProject asset.

  • Add a UYarnDialogueRunner component to an actor, assign your imported Yarn Project asset, and call StartDialogue().

  • VariableStorage (BlueprintReadWrite) -- where game state is stored (auto-created if not set)

  • DialoguePresenters (BlueprintReadWrite) -- array of presenter components that receive lines and options

  • LineProvider (BlueprintReadWrite) -- localisation provider (auto-created if not set)

  • CommandHandlerObjects (BlueprintReadWrite) -- array of objects with functions matching command names

  • SaliencyStrategy (BlueprintReadWrite) -- how to pick between competing content candidates

  • bRunSelectedOptionAsLine (BlueprintReadWrite) -- re-display the chosen option as a line of dialogue

  • bVerboseLogging (BlueprintReadWrite) -- log all VM execution for debugging

  • IsDialogueRunning -- check if active

  • Continue -- advance to next content

  • RequestHurryUp / RequestNextLine / RequestHurryUpOption -- cancellation flow

  • SelectOption -- pick an option by index

  • GetCurrentNodeName -- get executing node name

  • GetCurrentCancellationToken / GetCurrentOptionsCancellationToken -- for presenter use

  • OnNodeComplete (NodeName) -- a node finished executing

  • OnUnhandledCommand (CommandText) -- unhandled command received

  • OnDialogueStarted / OnDialogueComplete -- dialogue lifecycle
  • OnNodeEnter / OnNodeExit (NodeName) -- node lifecycle

  • OnHurryUpRequested / OnNextLineRequested -- cancellation events

  • OnOptionsHurryUpRequested -- option cancellation

  • OnPrepareForLines (LineIDs) -- pre-load upcoming lines

  • StartAutoAdvanceTimer / CancelAutoAdvanceTimer -- timer management

  • GetDialogueRunner -- get the owning runner

  • IsHurryUpRequested / IsNextContentRequested -- check cancellation state

  • (BlueprintReadWrite) -- custom widget class
  • GetDialogueWidget() (BlueprintCallable) -- get the widget instance

  • bShowLastLine -- show the last line above options

  • bUseFadeEffect / FadeInDuration / FadeOutDuration -- fade effects

  • bEnableKeyboardNavigation -- keyboard/gamepad navigation

  • NavigateUpKey / NavigateDownKey / ConfirmKey (and alternates) -- configurable keys

  • /
    AreOptionsVisible
    -- query state
    (BlueprintReadWrite) -- audio component to use
  • GetVoiceOverClip (BlueprintNativeEvent) -- override to customise audio lookup

  • OnVoiceOverStarted / OnVoiceOverComplete (BlueprintAssignable) -- events

  • Clear -- remove all variables (BlueprintNativeEvent)

  • GetAllVariables -- get all variables as typed maps (float, string, bool)

  • SetAllVariables -- restore from typed maps (with optional clear)

  • GetAllVariablesAsMap -- get all as a single FYarnValue map

  • GetDebugString -- formatted debug output

  • AddStringChangeListener / AddNumberChangeListener / AddBoolChangeListener -- per-variable callbacks

  • RemoveChangeListener -- remove a callback

  • RegisterSmartVariableEvaluator / UnregisterSmartVariableEvaluator -- smart variable support

  • /
    SetLocaleCode
    (BlueprintCallable) -- runtime locale control
  • GetAvailableLocales (BlueprintCallable) -- list available translations

  • AddLocalizedString (BlueprintCallable) -- add runtime translations

  • bShowByDefault (BlueprintReadWrite) -- show at start

  • bAutoLogEvents (BlueprintReadWrite) -- auto-log dialogue events

  • ScreenAnchor (BlueprintReadWrite) -- position on screen

  • ToggleDebugHUD / ShowDebugHUD / HideDebugHUD / IsDebugHUDVisible (BlueprintCallable)

  • Project Inspection

    GetAllNodeNames, HasNode, GetNodeCount, GetLineCount, GetAllLineIDs, GetNodeTags, GetAllDeclaredVariableNames, GetDeclaredVariableDefaultValue

    Variable Access

    GetAllVariableNames, GetAllVariables, HasVariable, GetVariableAsString, GetVariableAsNumber, GetVariableAsBool, SetStringVariable, SetNumberVariable, SetBoolVariable

    Persistence

    DialogueRunner->AddCommandHandler(TEXT("shake"), [this](const TArray<FString>& Params)
    {
        float Intensity = FCString::Atof(*Params[0]);
        // shake the camera
    });
    <<shake 2.5>>
    <<fade 1.0>>

    License

    Installation

    How It Works

    Architecture

    Blueprint Support

    What You Can Do From Blueprints (No C++ Required)

    UYarnBlueprintLibrary

    Components

    UYarnDialogueRunner

    UYarnDialoguePresenter

    UYarnWidgetPresenter

    UYarnOptionsPresenter

    UYarnOptionWidget

    UYarnVoiceOverPresenter

    UYarnInMemoryVariableStorage

    UYarnBuiltinLineProvider

    UYarnDebugHUDComponent

    Custom Commands

    Localisation

    Voice Over

    GitHub Sponsors
    Patreon
    https://yarnspinner.dev/pre-release-feedback

    SaveVariablesToSlot, LoadVariablesFromSlot, DoesVariableSlotExist, DeleteVariableSlot

    Value Conversion

    MakeYarnValueFromString, MakeYarnValueFromNumber, MakeYarnValueFromBool, YarnValueToString, GetYarnValueTypeName

    Runner Helpers

    GetDialogueRunner (find on actor), GetAllDialogueRunners (find all in level)

    Yarn Spinner Console