Yarn Spinner for Unity 3.2 is OUT NOW

Version 3.2 of Yarn Spinner for Unity is out now! This release brings mostly small bugfixes and quality-of-life improvements, ahead of our larger upcoming 3.3 release where the entire underlying virtual machine has been rewritten. And it includes changes that make it compatible with the newly-rewritten Yarn Spinner for Visual Studio Code extension.

Get Yarn Spinner+ for Unity from the Unity Asset Store! Get Yarn Spinner+ for Unity from itch.io!

Markup Parsing#

In this version, we fixed some bugs which could occur if you ordered your markup strangely, used culture-invariant floating point values, or a few other weird edge cases. We also changed when the implied [character] markers are added, so you can make markup handlers that customise the appearance of the speaker name just like you would any other marked-up content.

This might seem like no change if you hadn’t realised before, but basically when processing a line, Yarn Spinner will change Mae: Hello! to:

[character name="Mae"]Mae: [/character]Hello!

And this is how the LineProvider can tell where to snip it if you ask for the line content sans speaker name, or the speaker name by itself.

If you have defined a custom [character] marker...Any registered replacement markup handler that actions a custom marker called character will now also action these extra markers. Keep this in mind if you see unexpected behaviour!

YSLS Files#

YSLS files are specially-structured JSON files that previously Unity could make to tell editors about behaviour defined in-engine, such as custom commands and functions. This is what stops VSCode from complaining about unrecognised commands if you’ve declared them elsewhere. Many people didn’t know about the setting to turn on the generation of these files, and for a while the editor functionality to search for and interpret these files had a serious bug. But it was years before anybody found it. Which should give you an idea of how many people were using that feature.

The fallback behaviour if a YSLS file wasn’t found (which was especially necessary for supporting engines which didn’t produce YSLS declaration files) was to use the C# compiler API Roslyn to query for any declarations it could find and declare them silently. However, this has all sorts of issues, ranging from value inference issues like not being able to use variables as command names, to discovery issues like not being able to declare things in separately-compiled modules or packages. So this method missed perfectly valid and declared commands and functions all the time, and didn’t have enough information for other features people wanted like command parameter validation.

Well, no more!

We have changed how engines produce these declarations files, made it the default setting, added a bunch of new diagnostic information to the file structure, and - after finding this new version to no longer fail silent all the time - removed the fallbacks. From here on, editor plugins will assume you have at least one YSLS file if you use any custom commands or functions.

The editor is no longer responsible for doing its own discovery, which puts the support of different engines back in the engine-side code where it belongs. And in making this change, we now finally have warnings if your command parameters are wrong!

If you don't use one of our supported game engines...We have also updated the Yarn Spinner Command-Line Tool to be able to produce YSLS files for any C#-based projects. If you use something else entirely, you may need to provide your own definitions as per the spec.

Enum Parameters(ish)#

With the addition of Enumeration types in Yarn Spinner last February, people have understandably wondered why they can’t use them as parameters or return types in functions or commands. We had intended to make this possible with the 3.0 release, but we got stuck on how to make this work most cleanly in the C# code generation side.

As a brief aside, you might be thinking “well I would simply do it like this”. And of course, we know many ways it could work, but we have to go through the deliberations and implications properly. But when it comes to features which rely on code generation or compilation artefacts, we have to be extremely strict with how they handle a huge range of potential scenarios. Both in terms of how functional and bug-free they are, but also how adaptable and understandable they are.

Because if you think about code in terms of how familiar users are with it, this gives us an idea of how annoying something will be for them to debug and fix if an issue arises. If an issue arises in code files they wrote, and they presumably understand best, it’s normal annoying. If it arises in code we wrote and they just installed, but comes with documentation and they can read the source files and hopefully understand a little, then it’ll probably take more time but it’s not totally unexpected just slightly more annoying. But if something goes wrong in this third type of file - that was silently created by a template during compilation, that nobody wrote, and that the user may not even realise exists - then it has the potential to be an enormous headache.

ANYWAY, we haven’t added proper Enum-typed parameters or return types just yet. However, we have added support for type-hinting which is a tiny bit of extra syntax for the same user experience in the meantime while we work on supporting them properly.

If you attribute any parameters inside a command or function declaration in C# as being a YarnEnumParameter attributed value, then the editor will behave like it would for an enum value (typo detection, bounded values, autocomplete suggestions, etc.).

So let’s say you have an enum in Yarn for the type of pet the player has.

<<enum Animal>>
  <<case Fish = "Fishy">>
  <<case Dog = "Good Boy">>
<<endenum>>

A function to use that value in C# might look like this:

[YarnCommand("pet")]
public static void PetAnimal(string enumValue)
{
    Debug.Log($"I pet the {enumValue}");
}

But if instead you now declare it with the type hint, you can declare this string parameter should correspond to a raw value from the Animal enum type. Editor suggestions will act accordingly.

[YarnCommand("pet")]
public static void PetAnimal([YarnEnumParameter("Animal")]string enumValue)
{
    Debug.Log($"I pet the {enumValue}");
}

There is also a new attribute for when a string parameter should represent the name of a dialogue node in this project:

public static void DoStuffWithNodeName([YarnNodeParameter]string nodeName)

Which, again, is used to tell VSCode that it should offer a list of node names. This allows the creation of complex commands for use cases like:

  • setting another node as the one to run if - during this conversation - an interruption event happens
  • setting a node as the one to return to if this dialogue ends
  • other custom control flow behaviour

Both the enum and node type hint attributes work on functions and commands.

Locali(s|z)ation#

String tables can now be told to always sort after adding new line entries, by enabling the setting in Edit -> Project Settings -> Yarn Spinner. This is slightly slower than the default (add new lines at the end), but is of course desired behaviour if your translators or voice actors want to go through lines in the order they appear in the script.

Any line IDs which are present in the table but have been removed from the source Yarn files will be sorted to the top for you to decide if you want to delete them.

You Can Finally Escape Colons in Lines!#

Hooray! Such a simple thing, and yet a complete implementation nightmare because of some internal details of the way the Yarn Spinner parser works. But it finally works, so you don’t have to keep inserting dummy colons at the start of lines which both have no speaker and also want to use a colon in text.

: The old way to do: this. // this still works
The new way to do\: this. // but maybe this is nicer

And Many Tiny Nitpicks and Bugfixes!#

  • Preventing a rare bug where, every time YarnProjectImporter runs, it could add new duplicate entries to the SourceFilePatterns array.
  • YarnProjectImporter now runs earlier in compilation, so that generated files are created sooner and prevent spurious warnings in the editor that can occur if something is looking for a file that doesn’t exist yet.
  • Fixed an issue where some times awaitable commands wouldn’t get registered properly.
  • Fixed some InterfaceContainer absolute headache behaviour where it could lose its connection randomly somehow 🫠
  • Changed the pattern matching that pairs line assets to line IDs so that the substring behaviour is smarter. You can now have assets for both thing_1 and thing_10 in your project without the logic sometimes matching line:thing_1 to both.
  • A few added fields and events to custom typewriters.
  • Passing an incorrect number or types of parameters to a command will now warn you during compilation, rather than waiting until runtime to error.

Editor Updates#

We’ve also released a brand new, almost entirely rewritten version of our editor extension, Yarn Spinner for Visual Studio Code. This is so big it deserves its own blog post, so look out for that sometime in April, but here’s a taste of what’s new:

The entire language server has been rewritten from scratch in TypeScript (replacing the old C# one), and it’s the same language server that now powers Try Yarn Spinner. It’s faster, more reliable, and provides much better diagnostics — including, finally, proper warnings when your command parameters are wrong.

The graph view has been completely overhauled. You can now view graphs per-file or across your entire project, with cross-file connections visible. Nodes can be clustered into groups using cluster: headers, and there’s a sticky-note style for annotation nodes. You can also export your graphs as Mermaid or GraphViz DOT format if you want to use them in documentation or presentations.

The dialogue preview has levelled up significantly. You can change saliency strategies on the fly, export self-contained HTML previewers, and character names get consistent colour-coding between the editor and the preview, so you always know who’s talking.

We’ve added spell checking support (with configurable dictionaries), inlay hints that show variable types inline, a visual editor for .yarnproject files, a template system for creating new projects with sample dialogue and configuration, and improved the voice-over spreadsheet exporter that can output to Excel or CSV with customisable columns.

Oh, and the new YSLS file support we mentioned above? The editor side of that is much better now too — no more silent errors or fallbacks, just proper declarations with proper validation. A brief guide is available in the docs now, with lots more to come.

We’ve also experimentally deployed the extension to Open VSX for folks using open-source editors like VSCodium, and potentially other VS Code-compatible editors.

You can install it right now from the VS Code Marketplace or from Open VSX. We’ll keep an eye on how it goes in Open VSX, since it relies on some extensions that may not always be available.

The new Yarn Spinner for Visual Studio Code extension, showing the editor, dialogue preview, and graph view side by side.

Keep an Eye Out for 3.3 News#

This 3.2 update is a big jumble of smaller features we’ve had on our radar for a while, but it was also motivated by the need to fix certain things before we broke everything again as we rewrite the whole underlying Virtual Machine that runs compiled Yarn programs in Unity (and C# Godot)! That rewrite is critical to fixing a bunch of uncommon but seriously annoying bugs to do with async behaviour.

But we’ll talk more about that in our next monthly update. That’s all for now!

Get Yarn Spinner+ for Unity from the Unity Asset Store! Get Yarn Spinner+ for Unity from itch.io!

Unless otherwise noted, the content of this post is licensed under Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0). Logos, screenshots, and artwork shown in this post remain the property of their respective owners and are not covered by this license. The Yarn Spinner logo and branding imagery are also not covered by this license.