Yarn Spinner を使えばゲームの会話機能を作れそうな

インターネットをご覧の皆さん こんばんは。
Yarn Spinner を触ってみたところ、なかなか面白かったのでメモがてら記事を書いてみます。

https://yarnspinner.dev/

試した時点の環境は

- Yarn Spinner v2.2.1
- Unity2021.3.10f1
- VSCode 1.71.2
- Yarn Spinner VSCode Extension v2.2.15

です。

# Yarn Spinner とは？
Secret Lab ( [https://secretlab.games/](https://secretlab.games/) ) が開発している、
**ゲームの会話機能を実現するツール**です。
![ScreenShot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191218/f4cda931-2214-25c2-3607-8f73e06cf570.png)
※上記スクショは公式ドキュメントの [サンプル](https://docs.yarnspinner.dev/unity-sample-projects/example-project-3) から引用させていただきました。

Yarn Spinner は以下のような特徴を持っています。
- 独自構文のテキストファイルで会話の記述が行える。
- 通常の会話だけでなく、選択肢等の分岐も記述できる。
- 自分で定義したコマンドを登録&呼び出しできる。
- 音声再生にも対応。
- ローカライゼーションの仕組みもある。
- VSCode の拡張機能で記述のサポートをしてくれる。<br/>( https://marketplace.visualstudio.com/items?itemName=SecretLab.yarn-spinner )
- 現在は Unity をサポート。
- MIT ライセンスのオープンソース。<br/> ( https://github.com/YarnSpinnerTool/YarnSpinner )<br/>( https://github.com/YarnSpinnerTool/YarnSpinner-Unity )

# Yarn scripts
Yarn Spinner では会話内容を Yarn Script ( *.yarn ファイル )というテキスト形式のファイルで記述します。
Yarn Script は大きく分けて、Node、Line（台詞）、Option（選択肢）、Command で構成されており、制御構文や変数なども使用できます。

https://docs.yarnspinner.dev/getting-started/writing-in-yarn

基本要素は Node 単位で、`---` と `===` で囲われたノード本文に
- Line (台詞) 
- Option (選択肢。 `->`で始まる行)
- Command/制御構文/変数等（`<<` `>>`で囲われた箇所）

が含まれます。
```:ノード構成
title: タイトル
---
台詞
キャラ名：台詞

-> 選択肢１
-> 選択肢２
===
```

```:Yarn scripts サンプル
title: Start
tags: background:fountain
---
<<set $gold to false>>
<<set $silver to false>>

きこりが佇んでいる。泉に斧を落としてしまったようだ。
すると女神が現れて

女神:よっこいしょ

<<jump Select>>
===
title: Select
tracking: always
---
<<if visited_count("Select") < 1>>
女神:あなたが落としたのはどちらの斧ですか？
<<else>>
女神:よくよく考えなさい
<<endif>>

-> 金の斧
    女神:金の斧を落としたのですね？
    -> はい
        <<jump ChooseGold>>
    -> よく見たら違いました。
        <<set $gold to true>>
        <<jump Select>>
-> 銀の斧
    女神:銀の斧を落としたのですね？
    -> はい
        <<jump ChooseSilver>>
    -> 勘違いでした。
        <<set $silver to true>>
        <<jump Select>>
-> 鉄の斧 <<if $gold and $silver>>
    <<jump ChooseIron>>
===
title: ChooseGold
---
女神:ある意味正直ものですね。
===
title: ChooseSilver
---
女神:え？銀？
女神:珍しいですよ。銀を選ぶ人。
===
title: ChooseIron
---
女神:正直ものですね。
===
```

## 独自コマンドの登録＆呼び出し
Yarn Script では独自に作成したコマンドを登録＆使用することもできます。
static なコマンドのほか、コンポーネントのメソッドとして登録することや、コルーチン形式のコマンドも登録できます。

https://docs.yarnspinner.dev/using-yarnspinner-with-unity/creating-commands-functions

```cs:YarnCommand 属性で登録
public class FadeCamera {
    // <<fade_camera>> コマンドを登録
    [YarnCommand("fade_camera")]
    public static void FadeCamera(bool fade_in) {
        Debug.Log($"Fading the camera! {fade_in}");
    }
}
```
```cs:手動登録
public class CustomCommands : MonoBehaviour {    
    [SerializeField] private DialogueRunner dialogueRunner;

    public void Awake() {
        // <<camera_look>> コマンドを登録
        dialogueRunner.AddCommandHandler<GameObject>(
            "camera_look",     // the name of the command
            CameraLookAtTarget // the method to run
        );
    }

    private void CameraLookAtTarget(GameObject target) {
        if (target == null) {
            debug.Log("Can't find the target!");
        }
        Camera.main.transform.LookAt(target.transform);
    }    
}
```
# Unity 上での会話再生
Unity では、主に Dialogue Runner と Dialogue View を使用して会話を表示します。 

https://docs.yarnspinner.dev/using-yarnspinner-with-unity/components

## Dialogue Runner
![DialogueRunner.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191218/b47b8e3a-f058-66fd-77a0-692885390e97.png)
Dialogue Runner は Yarn Script を解析＆再生するコアコンポーネントです。
指定された Yarn Script ( Yarn Project ) を解析して、解析された会話データ（ Line や Option 等 ）を Dialogue View に送信することで会話を再生します。
Dialogue View は複数登録することができ、それぞれの役割に応じて会話の表示や選択肢の提示を行います。

## Dialogue View
![LineView.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191218/429c91f4-d06d-ee00-5cc8-a5571d812ea6.png)
![OptionListView.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191218/be883882-5de8-1fd3-d5d0-07defbb4b2b4.png)
![OptionView.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191218/8cc5c414-c991-03fc-b994-d4951da5b07a.png)
Dialogue View は Dialogue Runner から受け取った会話データを表示するコンポーネントです。
標準で Line View や Options List View 等が提供されているので、UI 要素を設定するだけでも使用できます。
また、独自の Dialogue View を作成することもできるようです。

# おわりに

機能はほかにもありますが、[ドキュメント](https://docs.yarnspinner.dev/) がある程度まとまっているほか、オープンソースなので調べやすいのもありがたいところです。
実際に Yarn Spinner を使ったゲームもリリースされているようで、会話表現に必要な基本機能を網羅しているほか、拡張性もあるところが魅力だなと感じました。

以上 おつきあいいただきありがとうございました。