Wednesday, July 18, 2018

Darner's Digest, vol. 1

Darner's Digest is a series of occasional posts about the game dialogue system Yarn.

As I've written before, there are a variety of different narrative system plugins to use with Unity. Fungus is a full visual scripting solution ideal for beginners, Ink is great for text heavy games with huge word counts (like 80 Days), and Yarn / Yarn Spinner is a lightweight extensible Twine-like dialogue system for games about occasionally talking to characters (like Night In The Woods).

I don't know what's going on in the Fungus community, and I loosely follow Ink -- they are running an upcoming Ink Jam to encourage new users, and the maintainer Inkle Studios is doing exciting dynamic narrative research in Inkle with their upcoming game Heaven's Vault.

However, I can definitely speak to more detail about what's happening with Yarn these days though, so here's my attempt to recap:

I like Yarn because it is simple and doesn't try to do everything. Instead, it lets me implement my own “Yarn commands” and extend custom functionality when I need it. For example, if I want to change an NPC's facial expressions from a Yarn script, it's pretty easy to write a ChangeFace( ) function in C# and hook it back into a "changeface" Yarn command. (If you need a complete tool that does do everything without any modifications, then Yarn might not be the best choice for you.)

But one big problem that holds back Yarn, in my opinion, is the available writing tools. The original Yarn Editor isn't actively maintained by the project owner anymore, which is ok and understandable, but unfortunately the last editor version (from 2016) doesn't have validation, auto-complete, debugging, in-editor testing, or other crucial features for efficiently designing narrative systems.

Todor "Blurymind" Imreorov has forked the original project and added lots of new features to his version, and he has even ported the code to a newer JS framework (Electron instead of nw.js). Some of those updates are being migrated back to the original repo, but it's unclear to me if there's any clear vision / roadmap / direction for the original Yarn Editor anymore, and anyway only Blurymind's fork has built updated releases that you can actually download and use.

In the long-term, I'm watching a new Yarn editor called Jacquard in active development, with a promising new approach to writing Yarn scripts; you can test Jacquard version 0.5 here.

These tools are also part of two ongoing shifts for the future of Yarn:

(1) The Yarn "language" itself is getting a small reboot and overhaul because there's a lot of hacks and loose ends to tidy up. If you want to participate in some of those discussions and get involved, or like me, simply watch and desperately try to understand what all these smart people are saying ("abstract syntax tree"???) then check out the Yarn Spinner issues tracker or join the Narrative Game Dev slack.

(2) Yarn tools are getting big processor updates. Yarn Spinner (the main Yarn plugin for Unity C#) is adopting ANTLR, a more robust language processing engine for more powerful debugging and editor features. There's also new JS-based Yarn parsers like JHayley's wonderfully-named bondage.js seeing heavier use, especially in web-based Yarn systems, hopefully allowing for better language analysis and visualization aids for writers. In the longer term, there's also some nerd talk about starting to compile Yarn scripts into bytecode at editor-time, instead of parsing the plain-text Yarn scripts at player-time, and I'm sure there's a good reason for it but I don't remember.

And now let's end this exciting first edition of Darner's Digest with a Yarn tip. This one comes from Jonathan Levstein, about working with Yarn variables via C# code:

To read or "get" a Yarn variable via Unity C#, use "GetValue" on the Variable Storage component:

int myNumber = GetComponent<ExampleVariableStorage>().GetValue("$YarnVar").AsNumber;
string myStr = GetComponent<ExampleVariableStorage>().GetValue("$YarnVar").AsString;

To write or "set" a Yarn variable via Unity C#, create a Yarn.Value and then assign it on the Variable Storage component with "SetValue":

var coolNumber = new Yarn.Value(420);
GetComponent<ExampleVariableStorage>().SetValue("$bestNumber", coolNumber);

Until next time, fellow darners!