All pages
Powered by GitBook
1 of 13

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Nodes and Lines

Learn about nodes and lines in Yarn Spinner scripts.

Yarn Spinner Scripts are built up out of nodes. Nodes are where you put your dialogue. You can have as many nodes as you want in a file.

A single node
title: Start
---
Narrator: Hi, I'm the narrator for the documentation!
===

Each node has, at the very minimum, a collection of headers, and a body. All nodes have at least one header, which is the title. The title is the name of the node, and the body contains the Yarn script that contains your game's dialogue.

Nodes are used to separate out parts of the story, and make it easier to manage longer stories and branching.

Node headers can contain any number of lines with the structure key: value. This can be used to store additional information, such as the location the conversation is taking place.

The title of a node is important, because your game uses node titles to tell Yarn Spinner which node to start running. You also use the title of a node when you want to jump to another node. Node titles are not shown to the player.

Node titles must start with a letter, and can contain letters, numbers and underscores. Node names cannot contain a . (period).

For example, FirstNode, First_Node and Node1 are valid, but First Node, First.Node and 1stNode

The --- marker indicates where the body begins. After this point, you can put all of your Yarn script.

The === marker indicates where the node ends; after this point, you can begin another node.

The body of a node (that is, the content between the node start marker --- and the node end marker ===) is made up of three different kinds of content: lines, commands, and options.

When you write Yarn Spinner dialogue, just about every line of text that you write in a node is a line. When a node is run, it runs each line, one at a time, and sends it to your game.

A line of dialogue is just the thing you want some entity or character to say, usually beginning with the name of the entity speaking.

For example, consider the following Yarn Spinner script snippet from Night in the Woods:

When this code is run in the game, it looks like this:

Yarn Spinner sends each of these lines, one at a time, to the game. The game is responsible for taking the text, and presenting it to the player; in the case of Night in the Woods, this means drawing the speech bubble, animating each letter in, and waiting for the user to press a key to advance to the next line.

Lines of dialogue can contain just about any text, except for some special characters that Yarn Spinner uses to add extra information to a line.

If there is a set of characters without spaces before a colon (:) at the beginning of the line, Yarn Spinner will mark that as the name of the character. This information will then be passed to your game, so that you can change the way that lines are shown based on the character who's saying them. For example:

Nodes can also have a color: and a group: in their header, which specifies what colour the bar at the top a node is shown in, and the group they're gathered in, in the Graph View of the :

You can also set nodes to be Sticky Notes by adding style: note to the node header. This will render the nodes differently in the Graph View of the . The color: of the node will be respected too, if one is set, otherwise the Sticky Note will default to yellow:

You can learn more about in the section.

1

Write a story inside a single node using Try Yarn Spinner.

Use VS Code to write a tiny story of 5 to 10 lines, inside one node.


Here's our story, if you couldn't think of an idea:

2

Play your story the Preview mode inside VS Code

Use the Command Pallette to Preview your tiny story.

are not.
Mae: Well, this is great.
Mae: I mean I didn't expect a party or anything
Mae: but I figured *someone* would be here.
Mae: ...
Mae: Welcome home, Mae.
This is a line of dialogue, without a character name.
Speaker: This is another line of dialogue said by a character called "Speaker".
title: Start
---
Navigator: The quantum fluctuations are intensifying. We need to jump now.
Captain: But the calculations aren't complete. We could end up anywhere.
Navigator: The wormhole is collapsing. It's now or never.
Captain: Fine. Initiate jump sequence.
Navigator: Something's wrong. We're being pulled backward...
Captain: That's impossible. Unless...
Navigator: We're arriving before we left. We've become our own rescue mission.
===

Inside a Node

Lines

Write a simple story

Yarn Spinner Editor
Yarn Spinner Editor
Writing Yarn in VS Code
Lines of dialogue running in Night in the Woods.

Scripting Fundamentals

Get started with Yarn Spinner Scripting by working through the fundamentals in detail.

If you're here, you've worked through the , and setup the , and you're ready to dive into the details of writing dialogue with Yarn Spinner.

This section of the documentation will take you through the scripting fundamentals:

  • combining Nodes, Lines, Options, and Jumps for simple interactive narratives

  • using Detours, Variables, and Yarn Spinner's Flow Control features for more complex interactions

the basics of Commands and Functions in Yarn Spinner
  • running options Once, and Line Groups for flexibility and control

  • Once you've completed it, you can move to .

    Beginner's Guide
    Yarn Spinner Editor
    Advanced Scripting

    Line Groups

    Learn about using line groups, which allow Yarn Spinner to choose which content to run, depending on conditions.

    To give your dialogue more life and variety, you can also provide lines in a line group. When lines are in a line group, Yarn Spinner will choose one of them for you.

    Line groups are collections of lines that begin with a => symbol:

    In this example, the Captain will say "Navigator, fire the glitter torpedoes! That'll confuse the enemy ships!", and then Yarn Spinner will choose one of the subsequent lines to respond with.

    You can attach conditions to lines in a line group, to ensure that they only run when it’s appropriate to do so. Conditions can be any true or false expression, and can also be combined with the once keyword to ensure that a line can only run once:

    A line in a line group can also have additional lines belonging to it, which will run if the item is selected.

    title: Start
    ---
    Captain: Navigator, fire the glitter torpedoes! That'll confuse the enemy ships!
    => Navigator: *sighs deeply* Sir, we don't have 'glitter torpedoes.' Those were in your dream last night.
    => Navigator: *eyes roll skyward* Captain, weaponizing craft supplies is not part of standard space combat protocol.
    => Navigator: *Slumps shoulders in defeat* I'll... make a note in the log that you suggested tactical glitter, sir.
    ===
    => Guard: Greetings, citizen.
    => Guard: Hello, traveller.
    	Guard: Stay vigilant. // runs after 'Hello, traveller.'
    => Guard: Hail, adventurer! <<if $player_is_adventurer>>
    => Guard: I used to be an adventurer like you, but then I took an arrow in the knee. <<once if $player_is_adventurer>>

    Line groups are great for running ‘barks’ - collections of short lines that need to run in response to an in-game event. It can be useful to think of them like Yarn Spinner’s existing options -> syntax, but instead of the player choosing which content to run, the computer picks it for you:

    => Guard: Halt!
    => Guard: No entry!
    => Guard: Stop!

    Smart Variables

    Learn about using smart variables that determine their value at run-time.

    Smart variables in Yarn Spinner are a powerful way to improve your dialogue and narrative flows. Unlike regular variables that only change when explicitly set, smart variables recalculate their value every time they're accessed, based on the expression that defines them.

    Why Use Smart Variables?

    1. Code Readability: They make your dialogue scripts more readable by using meaningful names instead of complex conditions.

    2. Centralised Logic: Define a condition once and use it throughout your game.

    3. Maintenance: When game mechanics change, you only need to update the smart variable declaration, not every place it's used.

    4. Abstraction: They hide complex game state checks behind simple, descriptive names.

    Creating a smart variable in Yarn Spinner is straightforward: <<declare>> command followed by a variable name (with the $ prefix) and assign it an rather than a static value. The expression can use , or even reference other variables.

    For example: <<declare $is_powerful = $strength > 50 && $magic_ability >= 20>>.

    This smart variable will automatically update whenever the values of $strength or $magic_ability change, making your dialogue able to dynamically respond to the player's stats without additional code.

    Smart variables shine when you have conditions that you check frequently or that combine multiple factors. They're especially useful for:

    • Tracking complex character states

    • Monitoring game world conditions

    • Representing player achievements or quest status

    • Creating dynamic dialogue that responds to multiple game systems

    By using smart variables, you make your dialogue scripts more intuitive and maintainable while keeping your game logic organised.

    Enums

    Learn about creating enums, which allow you to create variables that are constrained to a specific set of values.

    In Yarn Spinner, enums let you create variables whose value is constrained to a pre-defined list of possibilities.

    An enum (short for ‘enumeration’) is useful when you have a variable that needs to have a wider range of possible values than simply true or false, but needs to be more specific than a number or string.

    To define an enum you must provide a name, and some cases for it. Here's a new enum called Food with the cases Apple, Orange, and Pear:

    <<enum Food>>
      <<case Apple>>
      <<case Orange>>
      <<case Pear>>
    <<endenum>>

    Once you've created an enum, you can use it just like any other variable:

    // Declare a new variable with the default value Food.Apple
    <<declare $favouriteFood = Food.Apple>>
    
    // You can set $favouriteFood to the 'apple', 'orange' or 'pear'
    // cases, but nothing else!
    <<set $favouriteFood to Food.Orange>>
    
    // You can use enums in if statements, like any other type of value:
    <<if $favouriteFood == Food.Apple>>
      I love apples!
    <<endif>>
    
    // You can even skip the name of the enum if Yarn Spinner can 
    // figure it out from context!
    <<set $favouriteFood = .Pear>>

    Once

    Learn about once statements, which let you specify content that only runs once.

    Sometimes it's useful to create lines of dialogue that can only ever be displayed once.

    In Yarn Spinner Scripts, you can use a once statement to denote content that can only be run one single time. When the script reaches a once statement, it checks to see if it’s run before. If it has, it skips over it! Magic.

    once statements are great for making sure that the player never sees certain content more than once. For example, you might want a character to never introduce themselves to the player twice.

    There are two main ways you can use a once statement, which we'll explore below.

    You can wrap some lines in <<once>> and <<endonce>>:

    <<once>>
      // The guard will introduce herself to the player only once. 
      Guard: Hail, traveller! Well met.
      Guard: I am Alys, the guard!
    <<endonce>>

    You can also use an <<else>> clause within the <<once>> statement, which will be run if the relevant <<once>> content has already been seen:

    You can also add an if to the once to run content a single time, but only when a certain condition is true. In all other cases, it will be skipped (or the else content will be run, if there is any):

    If you add once (or once if) to a line, that line will only appear once, and will be skipped over every other time it’s encountered:

    Similarly, if you add it to an option, that option will only be selectable once, and will be marked as unavailable after it’s been selected.

    once statements are really useful when you want to show long, detailed content the first time it’s encountered, but you don’t want to show it every time. This means that players don’t need to mash the ‘skip line’ button over and over when they realise that they’re starting to see a long run of lines they’ve already seen:

    Commands

    Learn about using Commands in Yarn Spinner.

    In Yarn Spinner, you can send instructions to your game through commands. Commands look like this:

    <<wait 2>>
    <<setsprite ShipName happy>>
    <<fade_out 1.5>>

    Commands are sent to your game's Dialogue Runner, just like lines and options are. Commands are not shown to the player directly; instead, they're used for things like stage directions.

    Yarn Spinner comes with some built-in commands; however, to get the most usefulness out of them, you'll want to define your own custom commands that make your game do what you need to.

    Built-in Commands

    There are two built-in commands in Yarn Spinner: wait, and stop.

    wait

    The wait command pauses the dialogue for a specified number of seconds, and then resumes. You can use integers (whole numbers), or decimals.

    // Wait for 2 seconds
    <<wait 2>>
    
    // Wait for half a second
    <<wait 0.5>>

    stop

    The stop command immediately ends the dialogue, as though the game had reached the end of a node. Use this if you need to leave a conversation in the middle of an if statement, or a shortcut option.

    You can create your own commands, so that your scripts can send directions to your game. For more information on how to create them in Unity games, see , in the Yarn Spinner for Unity section of the documentation, and equivalents for other engines.

    Jump Command

    Learn to use the jump command to move the narrative between nodes.

    The <<jump>> command lets you move the dialogue between nodes. It is used by writing << then the word jump, a space, and then the full title of the node you want to jump the narrative to, then another >>.

    To jump to a node with the title Rescue_the_Kitten , for example, you would write the line <<jump Rescue_the_Kitten>>.

    Jump commands should always be placed on their own line, indented as appropriate.

    For example, consider the following conversation, which could be structured inside one node, using nested options, or split over several nodes using options and jump commands. The before version is inside a single node, and works fine, but the after version is structured across multiple nodes, and is a lot easier to make sense of.

    Practical Examples

    Example 1: Character Relationships

    Example 2: Item Availability

    Example 3: Time-Based Events

    Benefits in Complex Games

    expression
    mathematical operations, logical comparisons

    Making Your Own Commands

    We recommend that you only move into the Yarn Spinner for Unity documentation after learning the fundamentals of Yarn Spinner Scripting.

    Creating Commands and Functions
    <<declare $player_is_friends_with_sam = $sam_relationship_score > 50>>
    
    <<if $player_is_friends_with_sam>>
      Sam: Hey buddy! Good to see you again.
    <<else>>
      Sam: Oh, it's you. What do you want?
    <<endif>>
    <<declare $has_enough_materials = $wood >= 5 && $nails >= 10>>
    <<declare $has_required_skill = $carpentry_level >= 3>>
    <<declare $can_build_chair = $has_enough_materials && $has_required_skill>>
    
    <<if $can_build_chair>>
      Craftsman: You've got everything you need to build that chair now.
    <<else>>
      <<if !$has_enough_materials>>
        Craftsman: You'll need more materials first.
      <<else>>
        Craftsman: Your carpentry skills aren't quite there yet.
      <<endif>>
    <<endif>>
    <<declare $is_evening = $game_hour >= 18 && $game_hour < 22>>
    <<declare $town_shops_open = !$is_holiday && $game_hour >= 9 && $game_hour < 18>>
    
    <<if $is_evening && !$town_shops_open>>
      Innkeeper: Most shops are closed now, but you're welcome to stay here for the night.
    <<endif>>
    // Leave the dialogue now
    <<stop>>
    
    // Leave the dialogue if we don't have enough money
    <<if $money < 50>>
        Shopkeeper: You can't afford my pies!
        <<stop>>
    <<endif>>
    title: Start
    ---
    Navigator: Where to, Captain?
    
    -> Captain: I want to go back to earth!
        Navigator: Earth it is sir. 
        Navigator: This jump will take us 10 hours.
        Navigator: Permission to jump, sir?
        -> Captain: Granted, let's go!
            Navigator: On it, sir.
        -> Captain: Not yet. Just wait a moment.
    
    title: Start
    ---
    Navigator: Where to, Captain?
    
    -> Captain: I want to go back to earth!
        <<jump Earth>>
    -> Captain: Second star to the left!
        <<jump SecondStar>>
        
    
    Navigator: Being a Navigator sure is hard work!
    ===
    
    title: Earth
    ---
    Navigator: Earth it is sir. 
        Navigator: This jump will take us 10 hours.
        Navigator: Permission to jump, sir?
        -> Captain: Granted, let's go!
            Navigator: On it, sir.
        -> Captain: Not yet. Just wait a moment.
            Navigator: Standing by, sir.
    <<jump Done>>
    ===
    
    title: SecondStar
    ---
    Navigator: Can you be more specific?
        -> Captain: I cannot, no.
            Navigator: Right away, sir.
        -> Captain: ... that one *gestures*
            Navigator: Very good, sir.
    <<jump Done>>
    ===
    
    title: Done
    ---
    Navigator: Being a Navigator sure is hard work!
    ===

    Separating dialogue segments into nodes can aid in writing neater files that are easier to edit as they grow.

    When you use <<jump>> command, they'll be shown in the Graph View in Yarn Spinner for Visual Studio Code as an line with an arrow leading to the node that's being jumped to:

    The <<jump>> command being visualised in the Graph View.

    If you use the <<jump>> command to jump to a node that's in a different .yarn file, it will be visualised as a line leading to a small circle:

    1

    Write a simple story with several nodes.

    Spread your story out over the nodes in a sensible manner.

    2

    Use the <<jump>> command to move between nodes in your story.

    Make sure you specify the name of the node you want to jump to inside each <<jump>> command.

    3

    Run your story using Preview.

    Play through it, and make sure the jumps behave as you'd expect.

    Next up, learn about the Jump Command's close relative, the Detour Command.

    Using the Jump Command

    Write some Jump Commands

    <<once>>
      Guard: Hail, traveller! Well met.
    <<else>>
      Guard: Welcome back.
    <<endonce>>
    <<once if $player_is_adventurer>>
      // The guard knows the player is an adventurer, so say this line, 
      // but only ever once!
      Guard: I used to be an adventurer like you, but then I took an arrow in the knee.
    <<else>>
      // Either the player is not an adventurer, or we already saw the 
      // 'arrow in the knee' line.
      Guard: Greetings.
    <<endonce>>
    Guard: Who are you? <<once>> // Show this line only one time
    Guard: Go on, get lost!
    -> What's going on? <<once>>
    	Guard: The kingdom is under seige!
    -> Where can I park my horse? <<once if $has_horse>>
    	Guard: Over by the tavern.
    -> Lovely day today!
    	Guard: Uh huh.
    -> I should go.
    	Guard: Please do.
    <<once>>
    	// Show long, character-establishing lines the first time
    	Guard: There's nothing new to report!
    	Guard: I've been at this post for hours, and I'm so bored.
    	Guard: I can't wait for the end of my watch.
    <<else>>
    	// Show a more condensed version all other times
    	Guard: Nothing to report!
    <<endonce>>

    You can add <<once>> to a line, or options:

    once statements keep the information about whether they’ve been run or not in a variable that’s stored in your Dialogue Runner’s Variable Storage, just like any other variable. The variable isn’t directly accessible from your Yarn scripts.

    Functions

    Learn about Yarn Spinner's built-in functions.

    A function is a block of code that provides a value to your Yarn scripts, which you can use in if statements, or store in variables.

    In Yarn Spinner scripts, functions perform two main kinds of task:

    • Functions let you get values that change over time, or that depend on other values. For example, the random function returns a different random number every time you call it.

    • Functions let you get data from your game back into your scripts.

    You call a function inside an expression. For example:

    Yarn Spinner comes with several built-in functions for you to use.

    visited returns a boolean value of true if the node with the title of node_name has been entered and exited at least once before, otherwise returns false. Will return false if node_name doesn't match a node in project.

    visted_count returns a number value of the number of times the node with the title of node_name has been entered and exited, otherwise returns 0. Will return 0 if node_name doesn't match a node in project.

    format_invariant returns a string representation of n, formatted using the invariant culture. This is useful for embedding numbers in commands, where the command expects the number to be formatted using the invariant culture. For example, <<give_gold {$gold}>>, which might end up as give_gold 4,51 in German, but give_gold 4.51 in English, can now be <<give_gold {format_invariant($gold)}>>, which will always be give_gold 4.51.

    random returns a random number between 0 and 1 each time you call it.

    random_range returns a random number between a and b, inclusive.

    dice returns a random integer between 1 and sides, inclusive.

    For example, dice(6) returns a number between 1 and 6, just like rolling a six-sided die.

    min compares a and b, and returns the smaller of the two.

    max compares a and b, and returns the larger of the two.

    round rounds n to the nearest integer.

    round_places rounds n to the nearest number with places decimal points.

    floor rounds n down to the nearest integer, towards negative infinity.

    ceil rounds n up to the nearest integer, towards positive infinity.

    inc rounds n up to the nearest integer. If n is already an integer, inc returns n+1.

    dec rounds n down to the nearest integer. If n is already an integer, dec returns n-1.

    decimal returns the decimal portion of n. This will always be a number between 0 and 1. For example, decimal(4.51) will return 0.51.

    int rounds n down to the nearest integer, towards zero.

    You can create your own commands, so that your scripts can send directions to your game. For more information on how to create them in Unity games, see , in the Yarn Spinner for Unity section of the documentation, and equivalents for other engines.

    Options

    Learn to use options, which allow your players to choose lines of dialogue.

    When you want to let the player decide what to say, you use an option. Options let you show multiple potential lines of dialogue to the player, and let the player select one.

    Options are lines prefixed with a ->. You write as many options as you'd like the player to see, and the player chooses one of them. The content of the option is like any other line of dialogue.

    For example, consider the following code:

    In this example, the line Navigator: We're arriving before we left. We've become our own rescue mission. will run.

    The player will then be given the choice for the Captain to say either Let's alter our trajectory and break this temporal loop!, or We must complete the cycle. Our past selves depend on it.

    Detour Command

    Learn about detour and return, which let you temporarily move to another node, then return.

    In addition to using the to move between nodes, you can also use a detour command.

    A detour command looks very similar to jump: it takes a single parameter with the title of the node you want to move to, but unlike the jump command the detour command will return to the node that called it afterwards.

    The detour command works much like the jump command, except it will return to the node it detoured from after that node is done. Here’s an example of it in action:

    If the player replies No? to the guard’s question, Yarn Spinner will detour to the node titled Guard_Backstory and run its contents.

    When the end of the Guard_Backstory

    Navigator: Standing by, sir.
    -> Captain: Second star to the left!
    Navigator: Can you be more specific?
    -> Captain: I cannot, no.
    Navigator: Right away, sir.
    -> Captain: ... that one *gestures*
    Navigator: Very good, sir.
    Navigator: Being a Navigator sure is hard work!
    ===
    Writing Yarn in VS Code

    Built-In Functions

    visited(string node_name)

    visited_count(string node_name)

    format_invariant(number n)

    random()

    random_range(number a, number b)

    dice(number sides)

    min(number a, number b)

    max(number a, number b)

    round(number n)

    round_places(number n, number places)

    floor(number n)

    ceil(number n)

    inc(number n)

    dec(number n)

    decimal(number n)

    int(number n)

    This is different to floor, because floor rounds to negative infinity.

    Custom Functions

    We recommend that you only move into the Yarn Spinner for Unity documentation after learning the fundamentals of Yarn Spinner Scripting.

    Functions are not intended to be a way for you to send instructions to your game. For that purpose, you should use commands.

    As much as possible, custom functions should be pure functions, and have no side effects besides returning a value based on parameters.

    Creating Commands and Functions
    // Inside an if statement:
    <<if dice(6) == 6>>
        You rolled a six!
    <<endif>>
    
    // Inside a line:
    Gambler: My lucky number is {random_range(1,10)}!
    Options that are grouped together are delivered together, for example, consider the following updated script:

    In this example script these two options will be delivered together:

    As will these, separately:

    Two sets of options in the same node being displayed separately.

    Options can have their own lines, which are run when the option is selected. If a different option is selected, they won't run. To write this, indent the lines that belong to an option.

    In the following code, different lines will run based on which of the two shortcut options are selected.

    When the player has the choice of saying either "Let's alter our trajectory and break this temporal loop!", or "We must complete the cycle. Our past selves depend on it."

    Depending on their choice, the Navigator will say "Risky, Captain. We'd be writing ourselves out of existence." or "Then we're doomed to repeat this moment... forever.". Finally, no matter what was selected, the line "Sounds good!" will run.

    You can also nest options below other options. For example, consider the following snippet of Yarn Spinner Script:

    In this example script, the following options will be delivered together:

    And then, depending on which one was chosen, another set of options will be delivered together.

    For example, if the player chooses Captain: Let's alter our trajectory and break this temporal loop! , then the line from the Navigator will be delivered (Navigator: Risky, Captain. We'd be writing ourselves out of existence. ) and then two options for the Captain will be provided:

    And if the player chooses Captain: We must complete the cycle. Our past selves depend on it. , then the line from the Navigator will be delivered (Navigator: Then we're doomed to repeat this moment... forever.) and then three options for the Captain will be provided:

    The different groups of options, showing when they're grouped using colours.
    1

    Add options to your tiny narrative.

    Consider adding some lines that belong to the options below them, too.

    2

    Run your single-node narrative using Preview

    Demo.yarn
    title: Start
    ---
    Navigator: The quantum fluctuations are intensifying. We need to jump now.
    Captain: But the calculations aren't complete. We could end up anywhere.
    Navigator: The wormhole is collapsing. It's now or never.
    Captain: Fine. Initiate jump sequence.
    Navigator: Something's wrong. We're being pulled backward...
    Captain: That's impossible. Unless...
    Navigator: We're arriving before we left. We've become our own rescue mission.
    -> Captain: Let's alter our trajectory and break this temporal loop!
    -> Captain: We must complete the cycle. Our past selves depend on it.
    ===
    Demo.yarn
    title: Start
    ---
    Navigator: The quantum fluctuations are intensifying. We need to jump now.
    Captain: But the calculations aren't complete. We could end up anywhere.
    Navigator: The wormhole is collapsing. It's now or never.
    Captain: Fine. Initiate jump sequence.
    Navigator: Something's wrong. We're being pulled backward...
    Captain: That's impossible. Unless...
    Navigator: We're arriving before we left. We've become our own rescue mission.
    -> Captain: Let's alter our trajectory and break this temporal loop!
    -> Captain: We must complete the cycle. Our past selves depend on it.
    Navigator: Ayee! We're all going to die!
    -> Captain: Nonsense! Keep yourself together!
    -> Captain: AHHHH! We're all going to die!
    ===
    -> Captain: Let's alter our trajectory and break this temporal loop!
    -> Captain: We must complete the cycle. Our past selves depend on it.
    -> Captain: Nonsense! Keep yourself together!
    -> Captain: AHHHH! We're all going to die!
    title: Start
    ---
    Navigator: The quantum fluctuations are intensifying. We need to jump now.
    Captain: But the calculations aren't complete. We could end up anywhere.
    Navigator: The wormhole is collapsing. It's now or never.
    Captain: Fine. Initiate jump sequence.
    Navigator: Something's wrong. We're being pulled backward...
    Captain: That's impossible. Unless...
    Navigator: We're arriving before we left. We've become our own rescue mission.
    -> Captain: Let's alter our trajectory and break this temporal loop!
        Navigator: Risky, Captain. We'd be writing ourselves out of existence.
    -> Captain: We must complete the cycle. Our past selves depend on it.
        Navigator: Then we're doomed to repeat this moment... forever.
    ===
    title: Start
    ---
    Navigator: The quantum fluctuations are intensifying. We need to jump now.
    Captain: But the calculations aren't complete. We could end up anywhere.
    Navigator: The wormhole is collapsing. It's now or never.
    Captain: Fine. Initiate jump sequence.
    Navigator: Something's wrong. We're being pulled backward...
    Captain: That's impossible. Unless...
    Navigator: We're arriving before we left. We've become our own rescue mission.
    -> Captain: Let's alter our trajectory and break this temporal loop!
        Navigator: Risky, Captain. We'd be writing ourselves out of existence.
        -> Captain: Damnit, Navigator! Nothing can stop me existing!
            Navigator: *sigh* Very well, Captain.
        -> Captain: By gods! You're right!
            Navigator: But it's only solution, I fear.
    -> Captain: We must complete the cycle. Our past selves depend on it.
        Navigator: Then we're doomed to repeat this moment... forever.
        -> Captain: If we're doomed, at least we'll be remembered as heroes.
            Navigator: .. if anyone remembers us at all
        -> Captain: Forever... forever... forever...
            Navigator: Sir?
        -> Captain: We must do it!
                Navigator: As always, sir, you're right.
    ===
    -> Captain: Let's alter our trajectory and break this temporal loop!
    -> Captain: We must complete the cycle. Our past selves depend on it.
    -> Captain: Damnit, Navigator! Nothing can stop me existing!
    -> Captain: By gods! You're right!
    -> Captain: If we're doomed, at least we'll be remembered as heroes.
    -> Captain: Forever... forever... forever...
    -> Captain: We must do it!

    Options and Lines

    Options within Options

    Testing out Options

    node is reached, Yarn Spinner will return to the node titled
    Guard
    , and resume from just after the
    detour
    statement.

    When you detour into a node, Yarn Spinner runs the content from that node just as if you’d used a jump statement. When you reach the end of the node, or reach a return command, Yarn Spinner will return to just after the detour command. A return command looks like <<return>>. There are no parameters.

    You can return early from a detoured node by using the return command. Doing so will return to just after the detour command as though the end of the node had been reached, for example:

    When you detour into a node, that node can itself detour into other nodes. If a detoured node uses a jump command to run another node, the return stack is cleared. If you detour into a node, and that node jumps to another node, Yarn Spinner won’t return to your original detour site.

    The flow of detours and returns (automatic and triggered by the return command) in this snippet.

    When you use <<detour>> command, they'll be shown in the Graph View in Yarn Spinner for Visual Studio Code as an line with an arrow at each end, from the node that's being detoured to the node that's being detoured to:

    The <<detour>> command being visualised in the Graph View.
    1

    Write a simple story with several nodes.

    Spread your story out over the nodes in a sensible manner.

    2

    Use the <<detour>> command to move between nodes in your story.

    Make sure you specify the name of the node you want to jump to inside each <<detour>> command.

    3

    Run your story using Preview.

    Play through it, and make sure the detours behave as you'd expect.

    Next up, learn about Variables in Yarn Spinner Scripts.

    title: Guard
    ---
    Guard: Have I told you my backstory?
    
    -> Yes.
    	Guard: Oh. Well, then.
    -> No?
    	<<detour Guard_Backstory>>
    
    Guard: Anyway, you can't come in.
    ===
    
    title: Guard_Backstory
    ---
    Guard: It all started when I was a mere recruit.
    // (five minutes of exposition omitted)
    ===

    Using the Detour Command

    Jump Command
    title: Guard
    ---
    Guard: Have I told you my backstory?
    
    -> Yes.
    	Guard: Oh. Well, then.
    -> No?
    	<<detour Guard_Backstory>>
    
    Guard: Anyway, you can't come in.
    ===
    
    title: Guard_Backstory
    ---
    Guard: Do you want the detailed version or the short version?
    
    -> Detailed.
    	<<detour Guard_Detailed_Backstory>>
    	Guard: I hope you enjoyed learning all that.. Anyway...
    -> Short.
    	Guard: Right, well, I was a recruit, then I wasn't.
    ===
    
    title: Guard_Detailed_Backstory
    ---
    Guard: It all started when I was a mere recruit.
    
    // (five minutes of exposition omitted)
    // (other stuff happens)
    
    Guard: Want to hear more?
    
    -> Yes.
    -> No.
    	<<return>>
    
    Guard: (speaks more garbage)
    ===

    Using Detour with the Return Command

    If Yarn Spinner reaches a return comand, and it hasn’t detoured from another node, it will stop the dialogue (that is, it will behave as though you had written a stop command.)

    Write some Detour Commands

    Flow Control

    Learn how to use logic and flow control in your Yarn Spinner Scripts.

    So far, you've learned how to use Nodes and Lines, Options, the Jump Command, the Detour Command, and Variables to write Yarn Spinner Scripts.

    Because it's actually a full programming language of its own, Yarn Spinner also supports flow control.

    Flow control takes several forms, including if statements, and conditional options.

    if statements

    In addition to storing information, variables are useful for controlling what's lines of dialogue are presented to the player. To do this, you can use if statements.

    An if statement allows you to control whether a collection of content is shown or not.

    When you write an if statement, you provide an expression, which is checked; if that expression evaluates to a true value, then all of the content in between the <<if>> and <<endif>> statements are run.

    For example, consider the following Yarn Spinner Script:

    This script will:

    • set a variable, $gold_amount, to 5;

    • show the line Player: I'd like to buy a pie!

    • use an if statement to see if $gold_amount is less than 10, and if that is the case, which it will be in this example, show the line Baker: Well, you can't afford one!

    You can use the elseif and else statements to handle different situations in an if statement.

    An elseif statement has an expression that gets checked if the if statement, or any previous elseif statements, don't run.

    An else statement doesn't have an expression, and runs if the if and any elseif don't run.

    For example, consider the following Yarn Spinner Script:

    This script will:

    • set a variable, $gold_amount, to 5;

    • show the line Player: I'd like to buy a pie!

    • use an if statement to see if $gold_amount is less than 10, and if that is the case, show the line Baker: Well, you can't afford one!

    You can have as many elseif statements as you want inside an if statement block, and you can use whatever you want inside, for example:

    In this example:

    • there are two variables, $gold_amount for tracking the player's currency, and $reputation for their reputation in town

    • an if statement first checks if their $gold_amount is greater than or equal to 5 and whether their reputation is greater than or equal to 8, if both of these are true, then the line

    When presenting to the player using the -> syntax, you may want to make some options not available. You can do this by adding a condition to the option, making it a conditional option.

    For example, if you have a variable that tracks your player's reputation points, called $reputation, you might want to make certain options only available if the value of $reputation is high enough.

    Conditions on options are done by adding an if statement to the end of the option. They look like this:

    When Yarn Spinner runs this collection of options, it will check the expression inside the if statement. If the expression is false, then the option will be marked as unavailable.

    If every option in a group is marked as unavailable, the game is allowed to tell Yarn Spinner that no option was selected. When this happens, Yarn Spinner will skip the options group, and run the next piece of content after the options.

    Variables

    Learn about storing data using variables in Yarn Spinner Scripts.

    Sometimes it makes sense for the options presented or the outcomes of selecting different options to vary based on other things the player has done or said up until this point. This requires the use of logic and variables, which we'll discuss in this section.

    Yarn Spinner Script is a full programming language, which means it has support for writing code that let you control how the dialogue in your game works. In this section, you'll learn how to use variables to control your dialogue.

    Variables store information. Variables can store one of three types of information: numbers, strings, and booleans.

    Every variable has a name. In Yarn Spinner, all variable names start with a dollar sign ($).

    Declaring a variable means telling Yarn Spinner that a variable exists, what it's meant to be used for, and what initial value it has.

    To declare a variable, you use the

    spinner
    spinner
    spinner
    • otherwise use a elseif statement to see if $gold_amount is less than 15, and if that is the case, show the line Baker: You can almost afford one!

    • otherwise use a else statement to provide a fallback, which will show the line Baker: You can afford a pie!

  • end the if statement block with an endif statement.

  • Merchant: You're rich enough and popular enough for me to serve you!
    is shown
    • otherwise the elseif statement checks if their $gold_amount is greater than or equal to 10 (making them very rich), or their $reputation is greater than or equal to 10 (making them very well regarded), and if either of these are true the line Merchant: I wouldn't normally, but I'll serve you! is shown

  • if neither set of conditions is true, then the else statement means the line Merchant: You're neither rich enough nor important enough for me to serve! will be shown

  • elseif and else

    The expression used in an if and elseif statement must result in a boolean value (that is, true or false.) For exame,<<if 1>> isn't allowed, but <<if 1 == 1>> is.

    Conditional Options

    Yarn Spinner always delivers every option in an option group to the game; it's up to the game to decide what to do with options that are marked as unavailable.

    For example, an unavailable option might be shown to the user, but not selectable, so that the user can see that they could have been able to say that if circumstances had been different.

    Fallback Content in Options

    options
    Operators
    <<set $gold_amount to 5>>
    
    Player: I'd like to buy a pie!
    
    <<if $gold_amount < 10>>
        Baker: Well, you can't afford one!
    <<endif>>
    
    <<set $gold_amount to 5>>
    Player: I'd like to buy a pie!
    
    <<if $gold_amount < 10>>
        Baker: Well, you can't afford one!
    <<elseif $gold_amount < 15>>
        Baker: You can almost afford one!
    <<else>>
        Baker: You can afford a pie!
    <<endif>>
    <<set $gold_amount to 5>>
    <<set $reputation to 10>>
    <<if $gold_amount >= 5 and $reputation >= 8>>
        // The player is both rich and popular
        Merchant: You're rich enough and popular enough for me to serve you!
    <<elseif $gold_amount >= 10 or $reputation >= 10>>
        // The player is either rich enough or popular enough to serve
        Merchant: I wouldn't normally, but I'll serve you!
    <<else>>
        // The player is dirt
        Merchant: You're neither rich enough nor important enough for me to serve!
    <<endif>>
    Guard: You're not allowed in!
    -> Sure I am! The boss knows me! <<if $reputation > 10>>
    -> Please?
    -> I'll come back later.
    Guard: Who goes there?
    
    // If the player is a thief, a royal visitor, or a merchant, then
    // go run the appropriate conversation for that. The player might be
    // some combination of the three, so let them choose.
    -> A thief! <<if $player_is_thief>>
        <<jump Guard_Thief_Conversation>>
    -> A royal visitor! <<if $player_is_royal_visitor>>
        <<jump Guard_RoyalVisitor_Conversation>>
    -> A merchant! <<if $player_is_merchant>>
        <<jump Guard_Merchant_Conversation>>
    
    // But if the player is NONE of those, then none of the options would have
    // been available. We'll fall through to here.
    
    Player: I'm nobody!
    <<jump Guard_Nobody_Conversation>>
    <<declare>>
    command:

    You may find it useful to create a special node (for example, titled Setup, or similar) that is used solely to <<declare>> all the variables your narrative uses. You don't need to run this node for the declarations to take effect.

    You put information into a variable by using the <<set>> command. For example, the following Yarn Spinner Script puts a string, "Hello, Yarn!", into a variable called $greeting:

    Variables in Yarn Spinner can store one of three types of information: numbers, strings, and booleans:

    Type
    Possible Values
    Examples

    Number

    Any whole or decimal number

    1, 2.5, 3468900, -500

    String

    Any sequence of letters, numbers and other characters, enclosed in quotes.

    Each variable can only store one type of value. Variables can change their value at any time, but they can never change their type.

    For example, the following Yarn Spinner Script will work:

    This works because while the value of each of the variable changes, the type doesn't change.

    However, the following Yarn Spinner Script will not work:

    This will not work because when they are declared, $myCoolNumber is set to a number, and $myFantasticString is set to a string, so they can only ever store that type of information.

    You can work with the values stored in variables.

    For example, numbers can be multiplied, strings can be combined, and boolean values can have logical operations (like and and or) applied to them. When values are used together like this, it's called an expression:

    An expression needs to be a single type. You can't work with values of different types in a single expression.

    For example, the following code will not work:

    Yarn Spinner provides built-in functions for converting between certain types:

    • The string() function converts values of any type into a string.

    • The number() function converts values of any type into a number (if it can be interpreted as one.)

    • The bool() function converts values of any type into a boolean value (if it can be interpreted as one.)

    These functions work within Yarn Spinner Scripts. They all work by passing in, between the ( and ), a value of any time, either directly or by referring to another variable, and they return the same value, converted to the appropriate type.

    For example, consider the following:

    In this snippet, we declare the variable $aNumber and assign it the default value of 42, so $aNumber will always store a number, and we declare the variable $aString and assign it the default value of "This is a string", so $aString will always store a string.

    Then, we use the <<set>> command to upate the value stored in $aString, and assign it the value of $aNumber (which is a number, and can't be assigned directly to a string) converted to a string using the string() function. Thus, $aString will then contain the string "42".

    Yarn Spinner supports the following logical operators. Most of these have multiple ways being written:

    • Equality: eq or is or ==

    • Inequality: neq or !

    • Greater than: gt or >

    • Less than: lt or <

    • Less than or equal to: lte or <=

    • Greater than or equal to: gte or >=

    • Boolean 'or'': or or ||

    • Boolean 'xor': xor or ^

    • Boolean 'not': not or !

    • Boolean 'and': and or &&

    Yarn Spinner also supports the following maths operators:

    • Addition: +

    • Subtraction: -

    • Multiplication: *

    • Division: /

    • Truncating Remainder Division: %

    • Brackets: ( to open the brackets and ) to close them.

    Yarn Spinner follows a fairly standard order of operations, and falls back to using left to right when operators are of equivalent priority.

    The order of operations is as follows:

    1. Brackets

    2. Boolean Negation

    3. Multiplication, Division, and Truncating Remainder Division

    4. Addition, Subtraction

    5. Less than or equals, Greater than or equals, Less than, Greater than

    6. Equality, Inequality

    7. Boolean AND, Boolean OR, Boolean XOR

    To show the contents of a variable, you put it inside braces ({ }) inside a line. The value of that variable will appear in its place. For example:

    <<set $variableName to "a string value">>
    The value of variableName is {$variableName}.
    The value of variableName is a string value.
    1

    Create a Yarn Spinner Script that uses variables.

    Create a new narrative that uses two variables that track a player name, and an amount of currency. Make sure you declare them.

    2

    Use the <<set>> command to update the value of the variables appropriately

    Make sure you remember the types!

    Declaring Variables

    You should always declare a variable before you first use it.

    /// The name of the player.
    <<declare $playerName = "Reginald the Wizard">>
    
    /// The number of gold pieces that the player has.
    <<declare $gold = 42>>
    
    /// Is the door to the dungeon unlocked?
    <<declare $doorUnlocked = false>>
    <<set $greeting to "Hello, Yarn!">>
    // Set some initial values in some variables
    <<declare $myCoolNumber = 7>>
    <<declare $myFantasticString = "wow, text!">>
    
    // Now change them!
    <<set $myCoolNumber to 8>>
    <<set $myFantasticString to "incredible!">>
    // Set some initial values in some variables
    <<declare $myCoolNumber = 7>>
    <<declare $myFantasticString = "wow, text!">>
    
    // This will NOT work, because you can't change types!
    <<set $myCoolNumber to "eight">>
    <<set $myFantasticString to 42>>
    // Stores 3 inside $numberOfSidesInATriangle
    <<set $numberOfSidesInATriangle = 2 + 1>>
    
    // Store 4 inside $numberOfSidesInASquare
    <<set $numberOfSidesInASquare = $numberOfSidesInATriangle + 1>>
    // This will NOT work, because you can't add a string and a number:
    <<set $broken = "hello" + 1>>
    <<declare $aNumber = 42>>
    <<declare $aString = "This is my string.">>
    <<set $aString = string($aNumber)>>

    If you use a variable without declaring it, Yarn Spinner will try to figure out what type it should have based on how it's being used in your scripts, as well as what initial value it should have - zero for numbers, false for booleans, and blank text for strings. When a variable is not declared, we call that an implicit declaration.

    If you declare a variable, you can make sure that the type of the variable is what you intend it to be. Declaring a variable also lets you control what the variable's initial value is, and lets you add descriptive comments that explain the purpose of the variable to other people (or to your future self!)

    Setting Variables

    As with node titles, variable names must not contain spaces. While they can contain a range of different characters the first character must be a letter. In general your variables will be made up of only letters, numbers and underscores.

    Variables and Types

    Variables cannot be empty. All variables are required to have a value.

    Variables and Expressions

    Operators

    Order of operations

    Using Variables in Lines

    Write a story that uses variables

    "Hello", "✓", "A whole sentence."

    Boolean

    Either the value true or the value false.

    true, false