➿Syntax Basics
The first step in our three-step beginner's guide to Yarn Spinner: learning the syntax of Yarn with Try Yarn Spinner.
Writing Yarn with Try Yarn Spinner
When you first start learning Yarn, the best tool to work with is Try Yarn Spinner, so fire up your web browser—no installation necessary!
Open your web browser, and navigate to Try Yarn Spinner at https://try.yarnspinner.dev
In Yarn, everything you write is text. Yarn files are just plain text files with a .yarn extension.
Everything inside a Yarn file is structured around nodes and lines.
In Try Yarn Spinner, the first node to run is always called Start, so we’ll write that now.
Copy and paste, or write, the above Yarn script into Try Yarn Spinner!
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.
So this node is titled “Start”.
Node titles are not shown to the player and must start with a letter, and can contain any letters, numbers and underscores, but cannot contain a period or other symbols.
Node headers can actually contain any number of lines with the structure key: value
. This can be used to store additional information, such as the in-game location the conversation is taking place.
If you put the above Yarn, or something very similar, into Try Yarn Spinner and click the Test button, you’ll see the dialogue appear in the right side of the screen.
Getting a bit more complex
Let’s make it a bit more complex. Update the Yarn to look like the following:
Update the script in Try Yarn Spinner to the above Yarn and try running it.
In this node, there are the following elements:
the header, with the node’s title
the
---
marker, which indicates where the body of a node beginssome lines, representing a Narrator speaking…
and the
===
marker, which indicates the end of a node
Let’s chat about lines…
Almost everything is a line 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, Yarn Spinner 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.
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:
Options provide choices within nodes
After the lines of the Narrator speaking you’ll notice some lines that are indented, and start with a ->
interspersed amongst other lines from the Narrator:
These lines are called options, and they are how you let the player decide what to say. Options let you show multiple potential lines of dialogue to the player, who is then able to choose one.
As you might’ve guessed, an option line is denoted by starting the line with a ->
After that, the content of the line is like any other line.
If you put the above, updated Yarn, or something very similar, into Try Yarn Spinner and click the Test button, you’ll see the dialogue appear in the right side of the screen, and as you progress through it, eventually you’ll hit some options, which are presented to the player:
Depending on the choice of option, one set of lines from the Narrator, reacting to the player’s choice, will be displayed.
Nesting options within options
You can also nest options inside other options:
Put the above script in Try Yarn Spinner, and click Test to run it!
The only new thing that’s happening here is that options are inside other options. If you play this, inside Try Yarn Spinner, then you’ll be able to interact with the options based on the choices you make.
Have lots of options can get complex, so it’s often a good opportunity to break your story up into nodes and jump between them. We’ll do that next.
Jumping between nodes
You might have noticed that it’s a bit hard for you, the writer, to follow what’s going on, when you start nesting too many options, have lots and lots of lines of dialogue, or a combination thereof.
When things start to become too much for a single node, you can break things into multiple nodes and use the <<jump>>
statement to, you guessed it… jump to another node.
Here’s an example of the <<jump>>
statement in action:
Put the above script in Try Yarn Spinner, and click Test to run it, and observe how the jumps work.
By now, hopefully, you’re seeing what’s going on here, but let’s go through it to make sure.
In this yarn script there are three nodes: Start
, Alright
, and Love
and, depending on the choice made by the player inside the Start
node, the conversation will jump to Alright
(if they’re a bit rude) or Love
(if they’re somewhat polite).
The jump statement is used to move the narrative to a different node, and takes a single parameter, which is the full title of the node you want to jump to, and you can see it in use in our Start
node:
Separating dialogue segments into nodes can aid in writing neater files that are easier to edit as they grow.
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 next.
Logic and variables
Of course, Yarn is actually a full programming language, which means it has support for writing code that stores information in variables.
Yarn has three types of variables, 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. | "Hello", "✓", "A whole sentence." |
Boolean | Either the value true or the value false. | true, false |
Variables can be declared, set, and checked.
You can learn more about this in the Writing in Yarn guide. We recommend finishing this Beginner's Guide first, though.
Declaring variables
A variable is declared using a declare statement. It looks like this:
This declare statement declares a new variable named $characterName
and stores the value "Shadowheart"
inside it. When you first declare a variable, that sets its type.
So this variable, $characterName
, will always be of type string, because we declared it with a string, "Shadowheart"
.
Here’s an example of declaring two more variables, one of type number, and one of type boolean:
Every variable you use must have a name; in Yarn, all variable names start with a dollar sign ($
).
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.
Your variable names will be made up of only letters, numbers and underscores.
Setting variables
Of course, it’s not much use to declare a variable, if you can’t update it later. We call updating the contents of a variable setting. A variable is set using the set statement.
Here’s how we’d update the $characterName
variable to a new name:
Because $characterName
was declared as type string, you cannot then set it to a number, or a boolean, so the following will not work:
A variable must always have a value. There is no concept of null, or an empty variable in Yarn.
Expressions and variables
You can work with the values inside variables. For example, numbers can be multiplied, strings can be added together, 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:
Operators
Yarn Spinner supports the following logical operators. Most of these have multiple ways being written:
Equality:
eq
oris
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&&
Maths operators
Addition:
+
Subtraction:
-
Multiplication:
*
Division:
/
Truncating Remainder Division:
%
Brackets:
(
to open the brackets and)
to close them.
Order of operations
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:
Brackets
Boolean Negation
Multiplication, Division, and Truncating Remainder Division
Addition, Subtraction
Less than or equals, Greater than or equals, Less than, Greater than
Equality, Inequality
Boolean AND, Boolean OR, Boolean XOR
Checking and using variables
Variables by themselves aren’t much good if they cannot have some sort of impact on your narrative. So, of course, they can!
The most straightforward way to use a variable is to show the contents of it in a line. To do this we refer to the variable by name inside a line, and put it inside braces, like this: {$characterName}
.
For example:
Put the above script in Try Yarn Spinner, and click Test to run it.
Using variables with flow control
In addition to storing information, variables are useful for controlling what's shown to the player. To do this, you use if
statements, elseif
statements, else
, endif
, statements.
An if
statement allows you to control whether a collection of lines is shown or not. When you write an if
statement, you provide an expression, which is checked.
The if
, elseif
, else
, and endif
statements look much like all the other statements we’ve been using: <<if>>
, <<elseif>>
, <<else>>
, and <<endif>>
.
Here’s an example:
Put the above script in Try Yarn Spinner, and click Test to run it.
In this example, after the Narrator meets the character, and says it’s nice to meet them, greeting them by name, we use <<if $charName is "Bruce">>
to check if the variable $charName
is set to the value "Bruce"
.
If it is, then we have some nice lines about the Narrator also being named that, otherwise we use <<elseif $charName is "Notbruce">>
to check if the variable $charName
is set to the value "Notbruce"
, and provide some lines from the Narrator if it is.
If $charName
is set to neither of those values, then we hit the <<else>>
statement, which catches all other possible values, and we provide some lines that say their name—whatever it is—is a lazy one. Then we hit the <<endif>>
statement, which ends the entire if statement.
Conditional options
When presenting options 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.
It’s important to remember that 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.
You can see this in action in Try Yarn Spinner, where unavailable options will be displayed with a strike though!
Update the following example to use a conditional option at some point:
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 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.
Yarn Spinner provides the following built-in functions:
visited(string node_name)
visited
returns a boolean value oftrue
if the node with the title ofnode_name
has been entered and exited at least once before, otherwise returnsfalse
. Will returnfalse
ifnode_name
doesn't match a node in project.
visited_count(string node_name)
visted_count
returns a number value of the number of times the node with the title ofnode_name
has been entered and exited, otherwise returns0
. Will return0
ifnode_name
doesn't match a node in project.
random()
random
returns a random number between 0 and 1 each time you call it.
random_range(number a, number b)
random_range
returns a random integer betweena
andb
, inclusive.
dice(number sides)
dice
returns a random integer between 1 andsides
, inclusive. For example,dice(6)
returns a number between 1 and 6, just like rolling a six-sided die.
round(number n)
round
roundsn
to the nearest integer.
round_places(number n, number places)
round_places
roundsn
to the nearest number withplaces
decimal points.
floor(number n)
floor
roundsn
down to the nearest integer, towards negative infinity.
ceil(number n)
ceil
roundsn
up to the nearest integer, towards positive infinity.
inc(number n)
inc
roundsn
up to the nearest integer. Ifn
is already an integer,inc
returnsn+1
.
dec(number n)
dec
roundsn
down to the nearest integer. Ifn
is already an integer,inc
returnsn-1
.
decimal(number n)
decimal
returns the decimal portion ofn
. This will always be a number between 0 and 1. For example,decimal(4.51)
will return0.51
.
int(number n)
int
roundsn
down to the nearest integer, towards zero.
For example, you can use functions inside if
statements, and in regular lines, as they largely behave like variables. For example:
Write some yarn using functions! We recommend the dice
function, the random_range
function, and the visited
and visited_count
functions.
Building narratives with Yarn scripts
So far, you’ve learned that Yarn scripts are plaintext files (stored outside of Try Yarn Spinner, they have the .yarn
extension). Let’s do a quick recap…
Yarn scripts are composed of nodes, which must always start with at least a title header followed by a ---
, and end with a ===
:
Inside each node are lines, which are simple lines of dialogue that are delivered to the player, and often have a character name at the beginning:
Lines can also be options, which provide choices to the player:
These options can be nested:
You can also have multiple nodes, and jump between them using the jump statement:
And you can declare variables of three different types—numbers, strings, and booleans—and use them in lines, and for flow control. You’ve also learned about conditional options and built-in functions.
The next example recaps everything you’ve learned so far, so build it up slowly, piece by piece, in a new Try Yarn Spinner tab, so you understand how it’s working. Try to improve it, or make it longer by adding conditional options and use of built-in functions.
With that all said, in the next part, we’ll take things further and start using Yarn Spinner for Visual Studio Code.
Last updated