Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Markup allows you to add attributes into your text, like [a]hello[/a]
. These attributes can be used by your game to do things like change the formatting of the text, add animations, and more.
When text is parsed, the tags are removed from the text, and you receive information about the range of the plain text that the attributes apply to.
Attributes apply to ranges of text:
Yarn Spinner will take this text, and produce two things: the plain text, and a collection of attributes. The plain text is the text without any markers; in this example it will be:
Attributes represent ranges of the plain text that have additional information. They contain a position, a length, and their name, as well as their properties.
In this example, a single attribute will be generated, with a position of 4, a length of 5, and a name of "wave".
Attributes are opened like [this]
, and closed like [/this]
.
Attributes can overlap:
You can put multiple attributes inside each other. For example:
You can close an attribute in any order you like. For example, this has the same meaning as the previous example:
Attributes can self-close:
A self-closing attribute has a length of zero.
The marker [/]
is the close-all marker. It closes all currently open attributes. For example:
Attributes can have properties:
This attribute 'wave' has a property called 'size', which has an integer value of 2.
Attributes can have short-hand properies, like so:
This is the same as saying this:
This attribute 'wave' has a property called 'wave', which has an integer value of 2. The name of the attribute is taken from the first property.
Properties can be any of the following types:
Integers
Floats
'true' or 'false'
Strings
Single words without quote marks are parsed as strings. For example, the two following lines are identical:
If a self-closing attribute has white-space before it, or it's at the start of the line, then it will trim a single whitespace after it. This means that the following text produces a plain text of "A B":
If you don't want to trim whitespace, add a property trimwhitespace
, set to false
:
You may want to show text containing the [
and ]
characters to your player. To prevent the markup parser from treating as special characters, you can escape them. Text that has been escaped will be treated as plain text, and will not be interpreted by the parser.
There are two ways to escape your markup: escaping single characters, and using the nomarkup
attribute.
[
and ]
charactersIf you need to escape a single square bracket character, put a backslash \
in front of it:
This will appear to the player as:
The backslash will not appear in the text.
If you need to show a blackslash in your text, use two blackslashes:
This will appear as:
nomarkup
AttributeIf you want to escape a longer run of text, or if you have many square brackets, escaping a single character at a time can be cumbersome. In these cases, you may want to escape an entire region of text, using the nomarkup
attribute. This attribute makes the parser ignore any markup characters inside it.
If you want to include characters like [
and ]
, wrap them in the nomarkup
attribute:
This will appear as:
character
AttributeThe character
attribute is used to mark the part of the line that identifies the character that's speaking.
Yarn Spinner will attempt to add this character for you, by looking for character names in lines that look like this:
The markup parser will mark everything from the start of the line up to the first :
(and any trailing whitespace after it) with the character
attribute. This attribute has a property, name
, which contains the text from the start of the line up to the :
. If a :
isn't present, or a character
attribute has been added in markup, it won't be added.
This means that the example above is treated the same as this:
You can use this to trim out the character names from lines in your game.
Certain attributes in Yarn Spinner's markup are "replacement" markers, which Yarn Spinner uses to insert or replace text based on the value of a variable. There are three built-in replacement markers:
The select
marker uses the value of a variable to choose an outcome.
The plural
marker uses the value of a number to decide on the plural class for that number.
The ordinal
marker uses the value of a number to decide on the ordinal class for that number.
All three of these markers have a property called value
, and use this to decide what text should be used in the line.
select
The select
marker is the simplest of the built-in replacement markers. It takes the value of the value
property, and uses that to choose a replacement.
It's especially useful for when you need to insert a gendered pronoun in a line:
plural
and ordinal
The plural
and ordinal
markers take a number in its value
property, and use that to determine the plural or ordinal number class of that value.
Different languages have different rules for how numbers are pluralised.
In many languages, the term you use to refer to a thing depends on the the number of that thing. This is known as a plural class: in English, you can have one apple, but many apples, and you have have one mouse, but many mice.
However, the rules vary significantly across different languages. English has two: "single", and "other". However, for example, Polish has multiple.
In English, you say "one apple, two apples, five apples".
In Polish, you say "jedno jabłko, dwa jabłka, pięć jabłek".
Notice how the Polish word for "apple", "jabłko", takes multiple forms as the number changes, whereas it takes two forms in English.
In Yarn Spinner, individual lines are replaced depending on the user's locale, but the logic surround them is not. This means that, if you want to be able to translate your game into multiple languages, you can't write Yarn code like this:
If you did it this way, the logic would only work for languages that have the same rules for plurals as English. (There are several of them that do, but far more that don't.)
Complicating this further, there are two main kinds of plural classes: cardinal plural classes, and ordinal plural classes.
Cardinal plural classes are the kind we just saw (for example, "one apple, two apples").
Ordinal plural classes refer to the positioning of a thing; in English, ordinal numbers are things like "1st, 2nd, 3rd."
As with cardinal plural classes, different languages have different ordinal plural classes.
plural
and ordinal
Yarn Spinner is able to take a number and the user's current locale, and determine the correct cardinal or ordinal plural class of that number, for that locale. You can then use the plural class to decide on what text to show.
plural
and ordinal
have a property called value
, just like select
. They then have a property for each of the current locale's plural classes. These can be:
one
two
few
many
other
The two markers differ based on what kind of plural class they work with:
plural
selects a number's cardinal plural class.
ordinal
selects a number's ordinal plural class.
Not every language uses every category; for example, English only uses "one" and "other" for cardinal plural classes.
For each of these properties, you provide the text that should appear.
For example:
You can include the actual value in the resulting text by using the %
character. This character will be replaced with the value provided to the value
property:
The ordinal
marker works similarly, but uses the ordinal plural class:
In Yarn Spinner, you can send instructions to your game through commands. Commands look like this:
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.
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.
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 . For more information on how to create them in Unity games, see Creating Commands and 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.
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 between a
and b
, inclusive.
dice(number sides)
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.
round(number n)
round
rounds n
to the nearest integer.
round_places(number n, number places)
round_places
rounds n
to the nearest number with places
decimal points.
floor(number n)
floor
rounds n
down to the nearest integer, towards negative infinity.
ceil(number n)
ceil
rounds n
up to the nearest integer, towards positive infinity.
inc(number n)
inc
rounds n
up to the nearest integer. If n
is already an integer, inc
returns n+1
.
dec(number n)
inc
rounds n
down to the nearest integer. If n
is already an integer, inc
returns n-1
.
decimal(number n)
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(number n)
int
rounds n
down to the nearest integer, towards zero.
This is different to floor
, because floor
rounds to negative infinity.
You can define your own custom functions in Yarn Spinner. For more information, see # Defining Commands and Functions .
Functions are not intended to be a way for you to send instructions to your game. For that purpose, you should use commands.
In particular, functions are not guaranteed to be called in the same order as they appear in your code, or even be called at all if Yarn Spinner believes the result can be cached. As much as possible, custom functions should be pure functions, and have no side effects besides returning a value based on parameters.
if
statementsIn addition to storing information, variables are useful for controlling what's shown to the player. To do this, you 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 code:
This example will set a variable, $gold_amount
, to 5. It will then show the line "I'd like to buy a pie!", and before it continues, it will check to see if $gold_amount
is less than 10. If that's the case (which it will be!), the line "Well, you can't afford one!" will run.
elseif
and else
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
For example:
This script will show different lines depending on the value of $gold_amount
. The checks are done from top to bottom, which means that in order for an elseif
or else
to run, all of the checks above it have to have failed.
If it's less than 10, the line "Well, you can't afford one!" will run.
Otherwise, if it's less than 15, the line "You can almost afford one!" will run.
Otherwise, the line "Here you go!" will run.
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.
When presenting options to the player, you may want to make some options not available. You can do this by adding a condition to the 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.
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.
Now that you know how to work with nodes, lines, options and variables, there's one last part of the Yarn language to learn about: commands.
Yarn Spinner is a tool for writers. In this section, you'll the syntax of Yarn, how to write Yarn scripts for use in your game. You'll also learn how to use the various tools that are available for creating your content.
You'll need an editor before you can write Yarn scripts, so we recommend checking out Editing with VS Code before going too far.
The Yarn language 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.
Type | Possible Values | Examples |
---|---|---|
Every variable has a name. In Yarn Spinner, all variable names start with a dollar sign ($
).
You put information into a variable by using the <<set>>
command. For example, the following code puts a string, "Hello, Yarn!"
, into a variable called $greeting
:
As with node titles, variable names must not contain spaces. They must be made up of only letters, numbers and underscores, and the first character must be a letter.
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 code will work:
This works because while the value of each of the variable changes, the type doesn't. However, the following code will not work:
Starting with Yarn Spinner 2.0, variables are never null
. All variables are required to have a value.
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:
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.)
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:
Yarn Spinner doesn’t manage the storage of information in variables itself. Instead, your game provides a variable storage object to Yarn Spinner before you start running dialogue.
When Yarn Spinner needs to know the value of a variable, it will ask the variable storage object you’ve given it. When Yarn Spinner wants to set the value of a variable, it will provide the value and the name of the variable. In this way, your game has control over how data is stored.
The specifics of how variables need to be stored will vary depending on what game engine you're using Yarn Spinner in. To learn more about variable storage in Unity, see Variable Storage.
In Yarn Spinner, all of your dialogue is stored in .yarn
files. Yarn files are just plain text files, which you can edit in any text editor.
Yarn Spinner files contain nodes. Nodes are where you put your dialogue. You can have as many nodes as you link in a file. Nodes are used to separate out parts of the story, and make it easier to manage longer stories and branching.
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.
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.
So FirstNode, First_Node and Node1 valid, but First Node and 1stNode are not.
Node names cannot contain a . (period).
Node names were able to contain a period in Yarn Spinner 1, and if your Yarn Spinner 1 .yarn
scripts have periods in the node names, then the will translate them (and all jumps and options related) to use a _
(underscore) instead.
If you're using a text editor to write Yarn scripts, you'll need to write the node's header.
If you're using a graphical editor to write Yarn scripts, like Yarn Editor, it will handle this for you, and you can skip this section.
The plain-text version of a Yarn node looks like this:
In this example, the node's title is Node_Title
, which is set on the first line in the title
header. You can also add any other headers that you want.
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 ---
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 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 code 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:
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 marked with a ->
symbol. 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 "Hi there! What do you feel like doing today?" will run. The player will then be given the choice to say either "I want to go swimming", or "I'd prefer to go hiking".
Shortcut 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 a shortcut option.
In the following code, different lines will run based on which of the two shortcut options are selected.
This script will start with the line, "Hi there! What do you feel like doing today?". The player then has the choice of saying either "I want to go swimming", or "I'd prefer to go hiking". Depending on their choice, either the line "Okay, let's go swimming" or "Cool, we'll go hiking then". Finally, no matter what was selected, the line "Sounds good!" will run.
In addition to containing lines, options can also contain other options.
You can nest options as much as you like. However, this can get a bit challenging to read. It's often a good idea to use the <<jump>>
command to jump to a different node:
Separating dialogue segments into nodes can for 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 in the next section.
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