🤖Commands and Functions
Defining Commands
You can define your own commands, which allow the scripts you write in Yarn Spinner to control parts of the game that you've built.
In Unity, there are two ways to add new commands to Yarn Spinner: automatically, via the YarnCommand
attribute, or manually, using the DialogueRunner
's AddCommandHandler
method.
The YarnCommand
attribute
YarnCommand
attributeThe YarnCommand
attribute lets you expose methods in a MonoBehaviour
to Yarn Spinner.
When you add the YarnCommand
attribute to a method, you specify what name the command should have in Yarn scripts. You can then use that name as a command.
If the method is static, you call it directly. For example:
If you save this in a file called FadeCamera.cs
, you can run this code in your Yarn scripts like this:
If the method is not static
, you call it with the name of the game object you want the command to run on.
For example:
If you save this in a file called CharacterMovement.cs
, create a new game object called MyCharacter
, and attach the CharacterMovement
script to that game object, you can run this code in your Yarn scripts like this:
You can also use methods that take parameters. Yarn Spinner will take the parameters that you provide, and convert them to the appropriate type.
Methods that are used with YarnCommand
may take the following kinds of parameters:
Type | Note |
---|---|
| Passed directly to the function. |
| Parsed as an integer using Convert.ChangeType. |
| Parsed as an integer using Convert.ChangeType. |
| The strings "true" and "false" are converted to their respective boolean values, |
| Yarn Spinner will search all active scenes for a game object with the given name. If one is found, that game object will be passed as the parameter; otherwise, |
| Yarn Spinner will search all active scenes for a game object with the given name, and then attempt to find a component of the parameter's type on that game object or its children. If one is found, that component will be passed as the parameter; otherwise, |
Method parameters may be optional.
For example, consider this method:
This command could be called like this:
Adding commands through code
You can also add new commands directly to a Dialogue Runner, using the AddCommandHandler
method.
AddCommandHandler
takes two parameters: the name of the command as it should be used in Yarn Spinner, and a method to call when the function is run.
If you want to add a command using AddCommandHandler
that takes parameters, you must list the types of those parameters.
For example, to create a command that makes the main camera look at an object, create a new C# script in Unity with the following code:
Add this script to any game object, and it will register the camera_look
in the Dialogue Runner you attach.
You can then call this method like this:
YarnCommand vs AddCommandHandler
We provide two different means of handling commands in Yarn Spinner, the AddCommandHandler
method and the YarnCommand
attribute. Both of these provide effectively the same functionality, and under-the-hood the YarnCommand
attribute is even a wrapper around the AddCommandHandler
call. So if there are two different ways to achieve the same thing when should you use each one?
The YarnCommand
attribute allows you to tag specific methods as being a command, Yarn Spinner will then automatically handle the binding and connection of the the command in text to the method call in C#. AddCommandHandler
method allows you to manually connect a method in C# to a command in Yarn, letting you set the name of the command and which method it connect to, giving you the control over the binding.
Most of the time we feel that the YarnCommand
attribute is the better option, it is easier to use and maps well to how we find most people use commands, that is to say calling specific methods on specific GameObjects. This convenience however does come at a cost of flexibility as your YarnCommands
either need to be on static methods or follow specific calling conventions which may not be what you need or want. The YarnCommand
works best in our opinion when your commands are calling into specific GameObjects in your scene, so it works very well for moving, animating, or changing characters and items in a scene. For larger gameplay changing moments such as loading new scenes, or moving between dialogue and the rest of your game, or for more global events like declaring a save should happen or an achievement has been unlocked the AddCommandHandler
method is better.
Finally the YarnCommand
attribute performs a search on your project to locate and bind commands to specific method calls which the AddCommandHandler
does not have to do. While for the most part this lookup will go by unnoticed, on larger projects you may find this adds a noticeable performance penalty.
Making Commands Using Coroutines
Coroutines can be commands. If you register a command, either using the YarnCommand
attribute, or the AddCommandHandler
method, and the method you're using it with is a coroutine (that is, it returns IEnumerator
, and yields
objects like WaitForSeconds
), Yarn Spinner will pause execution of your dialogue when the command is called.
For example, here's how you'd write your own custom implementation of <<wait>>
. (You don't have to do this in your own games, because <<wait>>
is already added for you, but this example shows you how you'd do it yourself.)
This new method can be called like this:
Defining Functions
Functions are units of code that Yarn scripts can call to receive a value.
In additon to the built-in functions that come with Yarn Spinner, you can create your own.
To create a function, you use the YarnFunction
attribute, or the AddFunction
method on a Dialogue Runner. These work very similarly to commands, but with two important distinctions:
Functions must return a value.
Functions are required to be
static
.
For example, here's a custom function that adds two numbers together:
When this code has been added to your project, you can use it like this:
Yarn functions can return the following types of values:
string
int
float
bool
Commands, Functions and Assembly Definitions
Yarn Spinner searches your code for methods that have the YarnCommand
and YarnFunction
attributes when your game first starts up, as well as when a Dialogue Runner is told to run a Yarn Project.
If the Yarn Project's "Search All Assemblies" option is turned on, every assembly definition is searched; if it's turned off, only the assembly definitions specified in the "Assemblies To Search" option is searched. Code that is not in an assembly definition is always included.
By default, Yarn Spinner searches every assembly definition. If you have a large codebase, putting all of the code that contains commands and functions in an assembly definition can reduce the amount of time Yarn Spinner needs to take to find all of the commands and functions.
If "Search All Assemblies" is turned off on your Yarn Projects, and you're seeing errors that mention that a command hasn't been registered, try turning "Search All Assemblies" on. If the error goes away, it means the code for those commands is in an assembly definition that the Yarn Project wasn't using.
Last updated