Hey, everyone! It’s been an incredible two years (nearly) since the release of Yarn Spinner 2.0, and we’ve been thrilled to see the tool develop into something that’s used to power thousands of incredible games.
We’ve been working away at new features for Yarn Spinner 3.0, and we wanted to give you a preview of what’s coming. We don’t currently have a date for Yarn Spinner 3.0, but we currently expect to ship it in the first half of the new year.
💡 All examples in this post are work-in-progress. The features may or may not ship at all, and features that do ship may not have the same syntax or the exact same behaviour as what’s described here.
To show your support in the mean time, send people to the Patreon, and buy Yarn Spinner, plus the new Add-Ons, at Itch!
Supporting sophisticated narrative structures
Yarn Spinner has always been great at creating branching dialogue systems. In Yarn Spinner 3, we’re adding new features to let you write more sophisticated, reactive narratives.
Storylets
A storylet is a ‘piece’ of a story that can be embedded into the larger narrative, and that the game’s systems decide which one to use depending on the current situation.
Storylets work by having multiple nodes that share a name. Each of these nodes has a when: header that specifies the conditions under which the node should be made available.
When Yarn Spinner needs to run one of these nodes, it first filters out any nodes whose conditions fail. Then, it chooses one of the remaining nodes using a saliency strategy. This is a strategy for deciding which particular node should be chosen - should it be random? Should it be the most specific one? Should it be the one that hasn’t been seen in a while?
For example, imagine you have three nodes that share the name “Guard”:
title: Guard
when: once
---
Guard: Hail, traveller! Well met.
Guard: I am Alys, the guard!
===
title: Guard
when: $has_sword
---
Guard: No weapons allowed in the tavern!
===
title: Guard
---
Guard: Good day to you.
===
When you run a node called “Guard”, Yarn Spinner will first check to see which nodes are available. If this is the first time running the node, the first one will be available (because of the once keyword). If the player has a sword, the second one will be available. The third one is always available, because it has no conditions.
Yarn Spinner will then choose one of the available nodes using a saliency strategy. The default strategy is “best”, which chooses the node with the most specific conditions. So, if this is the first time running the node and the player has a sword, the first node will be chosen (because it has two conditions, and the second node has one).
Line Groups
Line groups are a lightweight version of storylets, where a group of lines can be written, and the system decides which one to use.
Line groups are useful when you want to have some variety in the dialogue that’s presented to the player, but you don’t want to give them a choice about it.
Lines in a line group are prefixed with =>:
=> Guard: Halt!
=> Guard: No entry!
=> Guard: Stop right there!
When Yarn Spinner reaches a line group, it will choose one of the lines to run, using the same saliency system as storylets.
Like storylets, line groups can have conditions, and can use the once keyword:
=> Guard: Halt! <<if $player_is_sneaking>>
=> Guard: I used to be an adventurer like you... <<once if $player_is_adventurer>>
=> Guard: Stop right there!
Smart Variables
Smart variables are variables whose value is determined at runtime, rather than being set to a specific value when they’re declared.
For example, you might want to declare a variable that’s true when the player has more than 10 money. You could do this by checking the player’s money every time you want to use this variable, but that would be tedious. Instead, you can declare a smart variable:
<<declare $player_can_afford_pie = $player_money > 10>>
Now, whenever you use $player_can_afford_pie, Yarn Spinner will evaluate the expression $player_money > 10 and use that as the value.
Smart variables can be used anywhere that regular variables can be used, and they’re a great way to encapsulate complex expressions that you want to use in multiple places.
Enums
Enums are a way to give names to specific values, and to constrain variables to only have one of those values.
For example, you might want to have a variable that represents the player’s favorite food. You could use a string for this, but that would mean that typos could cause bugs. Instead, you can use an enum:
<<enum Food>>
<<case Apple>>
<<case Orange>>
<<case Banana>>
<<endenum>>
<<declare $favorite_food = Food.Apple>>
Now, the variable $favorite_food can only ever be set to Food.Apple, Food.Orange, or Food.Banana. If you try to set it to anything else, you’ll get a compile error.
Enums are a great way to reduce the number of “magic strings” or “magic numbers” in your dialogue, and to make your code more readable.
Once Support
The once keyword is used to mark content that should only appear once. The very first time a once keyword is reached, it’s treated as though it’s the value true. Every subsequent time, it’s treated as though it’s the value false.
<<once>>
Guard: Hail, traveller! Well met.
Guard: I am Alys, the guard!
<<endonce>>
You can also use once with a condition:
<<once if $player_is_adventurer>>
Guard: I used to be an adventurer like you...
<<else>>
Guard: Greetings.
<<endonce>>
The once keyword can also be used on individual lines and options to make them appear or be selectable only once.
Jump and Return
The detour statement (also known as jump and return) lets you run content from a different node, and then return to where you were.
This is useful when you have a piece of content that you want to be able to run from multiple places, but you want to return to the original location when it’s done.
<<detour Guard_Backstory>>
When you reach the end of the detoured node, or when you reach a return statement, Yarn Spinner will return to just after the detour statement.
Improving integration with game engines
We’re also working on improvements to how Yarn Spinner integrates with game engines, with a focus on Unity.
Improved Type System
Yarn Spinner 3 has an improved type system that supports all of the new language features, and provides better error messages when you make a mistake.
Shadow Lines
Shadow lines are a way to reuse lines across different parts of your dialogue, without having to duplicate them in your string tables.
When you mark a line as a shadow line, you’re telling Yarn Spinner that it should use the same localized content as another line. This is useful when you have a line that appears in multiple places, but you only want to translate it once.
title: Tavern
---
Ava: I should go. #line:departure
title: Kitchen
---
Ava: I should go. #shadow:departure
In this example, the line in the Kitchen node is a shadow of the line in the Tavern node. They’ll both use the same translated text.
Variable Change Events
Yarn Spinner 3 adds support for listening to changes in variables, so that you can update your UI or game state when a variable changes.
This is useful for things like updating a quest tracker when a quest variable changes, or updating a health bar when a health variable changes.
Async Dialogue Views
Dialogue Views in Yarn Spinner 3 are based on C#’s async/await system, which makes it much easier to write custom dialogue views.
The async/await system lets you write code that waits for things to happen without having to use callbacks, which makes your code much more readable and easier to reason about.
Your existing (non-async) dialogue view code will automatically work with Yarn Spinner 3, so you don’t need to change it if you don’t want to.
Auto-Generated C# Interfaces
Yarn Spinner 3 can automatically generate C# interfaces for your Yarn Projects, which gives you compile-time checked access to your variables and prevents typos.
This is a huge improvement over the old system, where you had to use strings to access variables, and typos would only be caught at runtime.
Better Command and Markup Support
Commands and markup in Yarn Spinner 3 are now type-checked at compile time, so you’ll get errors if you try to use a command or markup tag that doesn’t exist, or if you use it incorrectly.
Expanding to more platforms
We’re also working on expanding Yarn Spinner to more platforms.
Yarn Spinner for Unreal
Yarn Spinner for Unreal is getting close to beta! We’re currently working on the standard library and documentation, and we’re hoping to have it ready for testing soon.
Yarn Spinner for JavaScript / NPM
We’re also working on a Yarn Spinner runtime package for JavaScript, which will be available on NPM. This will make it possible to use Yarn Spinner in web-based projects, or in projects that don’t use a game engine.
We’re really excited about these features, and we can’t wait to see what you build with them! If you have any questions or feedback, please let us know on Discord or Twitter.