Functions
A Function lets a Yarn Script ask your game for a value, like how many coins the player has, or whether they’re carrying a key. You call it by name, with any arguments in brackets, and your game sends back the answer:
title: FunctionsDemo
---
<<if has_item("brass key")>>
Rosa: Good, you've got the key.
<<else>>
Rosa: You'll need a key to get up the stairs.
<<endif>>
<<set $coin_total to coin_count()>>
Rosa: You've got {$coin_total} coins.
===Where a Command tells your game to do something, a Function asks it a question. The dialogue uses the answer and carries on.
sequenceDiagram
participant R as Dialogue Runner
participant G as Your game code
Note over R: #60;#60;if has_item("brass key")#62;#62;
R->>G: HasItem("brass key")
G-->>R: returns false
Note over R: Shows "You'll need a key to get up the stairs."
Note over R: #60;#60;set $coin_total to coin_count()#62;#62;
R->>G: CoinCount()
G-->>R: returns 15
Note over R: Shows "You've got 15 coins."Using Functions in Yarn
You can use a Function anywhere Yarn expects a value:
- in a condition:
<<if has_item("brass key")>>, - in a
<<set>>:<<set $coin_total to coin_count()>>, - in an expression with other values:
<<if coin_count() >= 10>>.
Put text arguments in double quotes, like "brass key". Numbers, true and false, and variables go in as they are: has_item($chosen_item).
A Function can go directly inside a line, like Rosa: You've got {coin_count()} coins. When your C# scripts compile, Yarn Spinner tells the Yarn compiler about the Functions you’ve marked with [YarnFunction], including what each one returns.
Writing a Function
Functions marked with an attribute
Add the [YarnFunction] attribute to a static method, and give the attribute the Function’s name in Yarn:
using Yarn.Unity;
public static class TextFunctions
{
[YarnFunction("shout")]
public static string Shout(string text)
{
return text.ToUpperInvariant();
}
}If you leave the name out, the method’s name is used. Yarn Spinner finds these methods when your scripts compile, in the same way as it finds Commands, and adds them to every Dialogue Runner. See How attributed Commands are found.
The method has to be static, and it has to be public, in a public class. If it isn’t static, you’ll see error YS1006 in the Console when your scripts compile. If it isn’t public, you’ll see error YS1001.
Functions that use your game’s state
A static method can’t read the fields on a component, like an inventory. For a Function that needs to, add it to the Dialogue Runner with AddFunction():
using System.Collections.Generic;
using UnityEngine;
using Yarn.Unity;
public class PlayerState : MonoBehaviour
{
[SerializeField] DialogueRunner dialogueRunner;
readonly List<string> inventory = new List<string> { "lantern" };
int coins = 15;
void Awake()
{
dialogueRunner.AddFunction<string, bool>("has_item", HasItem);
dialogueRunner.AddFunction<int>("coin_count", CoinCount);
}
bool HasItem(string itemName)
{
return inventory.Contains(itemName);
}
int CoinCount()
{
return coins;
}
}static method couldn’t see these.has_item("brass key") in Yarn calls this. It returns a bool, so it can be used in an <<if>>.coin_count() returns a number.When you pass a method by name, list its parameter types and then its return type in angle brackets, like AddFunction<string, bool>. You can pass a lambda instead, giving its parameters types: dialogueRunner.AddFunction("double", (float n) => n * 2);.
To remove a Function, call dialogueRunner.RemoveFunction("has_item").
Two Functions can’t have the same name, and a Function can’t use the name of a built-in one. If you add a Function with a name that’s already taken, or one with a space in it, the Dialogue Runner logs an error and ignores it.
Values going in and out
A Function has to return one of the kinds of value Yarn understands:
| Return type | In Yarn |
|---|---|
bool | true or false. |
int, float, double and other number types | A number. |
string | Text. |
A Function marked with [YarnFunction] that returns anything else gives you error YS1004 when your scripts compile.
A Function must return its value immediately. It can’t make the dialogue wait, so it can’t be a coroutine or an async method.
Arguments are converted to the types of the method’s parameters. A Yarn number becomes an int, float or whichever number type the parameter has, and true and false become a bool.
Built-in Functions
These Functions are always available:
| Function | What it returns |
|---|---|
visited("NodeName") | true if the node has been run before. |
visited_count("NodeName") | How many times the node has been run. |
random() | A random number between 0 and 1. |
random_range(1, 6) | A random whole number from the first number to the second, including both. |
dice(6) | A random whole number from 1 to the number you give it, like rolling a die. |
round(n), floor(n), ceil(n) | The number rounded to the nearest whole number, down, or up. |
min(a, b), max(a, b) | The smaller or larger of two numbers. |
For maths there are also random_range_float, round_places, inc, dec, decimal and int. For converting between types there are string, number and bool.
Autocomplete in VS Code
The Yarn Spinner extension for VS Code suggests your Functions as you type, along with what they return. It reads them from the .ysls.json file that Yarn Spinner writes when your C# scripts compile. See The .ysls.json file.
For a scene that uses Commands and Functions together, see Putting It Together.