To allow a DialogueRunner to execute a C# method as a command from your Yarn dialogue, decorate the method with the [YarnCommand] attribute.
Command Resolution Logic
When a DialogueRunner encounters a command (e.g., <<move player fast>>):
- It splits the command by spaces.
- It checks if the second word is the name of an active
GameObject in the scene. - If a
GameObject is found, it searches its attached MonoBehaviour components for a method marked with [YarnCommand] where the Name matches the first word of the command. - If the method is
static, it does not attempt to resolve a GameObject and is called directly.
Parameter Mapping Rules
Once a method is identified, the DialogueRunner maps the remaining words in the command to the method's parameters:
| Parameter Type | Mapping Behavior |
|---|
string[] | Receives an array containing all words in the command after the first two. |
| Fixed number of parameters | If the number of words matches the parameter count, each word is passed as an individual parameter. |
GameObject | Uses GameObject.Find(string) to locate the object (must be active). |
Component | Locates the component on the GameObject found via GameObject.Find(string) (must be active). |
bool | Converts the string "true" or "false" to a boolean. Special Case: If the string matches the parameter name (case-insensitive), it is treated as true (e.g., <<move wait>> for a Move(bool wait) method). |
| Other types | Uses Convert.ChangeType with CultureInfo.InvariantCulture. You can implement IConvertible to support custom types. |
Note: If parameters cannot be matched or converted, the method will not be called and a warning will be issued.
Async and Coroutines
You can attach [YarnCommand] to IEnumerator (coroutines), Coroutine returning methods, or Task returning methods. The DialogueRunner will automatically pause dialogue execution until the coroutine or task completes.
using UnityEngine;
using Yarn.Unity;
using System.Collections;
public class PlayerController : MonoBehaviour
{
// Simple command: <<move player fast>>
[YarnCommand("move")]
public void MovePlayer(GameObject target, string speed)
{
Debug.Log($"Moving {target.name} at speed {speed}");
}
// Boolean command with self-documenting parameter: <<wait true>> or <<wait>>
[YarnCommand("wait")]
public void Wait(bool wait)
{
if (wait) StartCoroutine(WaitRoutine());
}
private IEnumerator WaitRoutine()
{
yield return new WaitForSeconds(1f);
}
// Static command (no GameObject required): <<set_score 10>>
[YarnCommand("set_score")]
public static void SetScore(int score)
{
Debug.Log($"Score set to: {score}");
}
}