YarnSpinner剧情编辑

本来说好的每周一更又鸽了…
今天来水一期,介绍一款很棒的剧情编排应用 YarnSpinner

介绍

YarnSpinner是一款开源免费的剧情编排应用(或者说是一种用于剧情编排的标记语言)。
试想我们在开发游戏时,剧情有分支选择,有各种条件检查,如果我们全在代码中去判断和检查不仅繁杂而且非常麻烦,策划学习成本高,耦合性过强。你可能自己想出一套标记语言来表述剧情流程,但自己的力量毕竟是有限的,难免出现一些bug和坑。此时,不妨试试这款免费开源,多人共同维护的应用吧。

快速食用

代码式编辑

这里我使用vscode作为编辑器,下载一下插件:
扩展

我们先创建一个.yarn格式的文件,并写入以下内容:

1
2
3
4
5
6
7
8
9
10
11
title: cc
tags:
colorID: 0
position: 1,-22
---
Fasty97: Hi
PC: 你好?!
Fasty97: 我又回来了!
PC: 是忘了什么东西吗?
===

这是一段剧本最基本的格式(一个yarn文件至少包含一段剧本):

1
2
3
4
title: cc
tags:
colorID: 0
position: 1,-22

以上被称为一个剧本头,表示一段剧本,这些是一些剧本段的基本信息,其中title必填,position必填.position为剧本段的标识符类似于ID一样的东西,不要重复。

在unity中使用

  1. 下载相关的unity支持包(官网有)
  2. 在场景中放入一个Dialogue预制体,预制体包含一个默认的设置示例。
  3. 创建一个脚本
  4. 设定好相关的资源和引用
  5. 运行游戏尝试按下空格键吧

脚本设定

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
using System;
using System.Collections.Generic;
using UnityEditorInternal;
using Yarn.Unity;
using UnityEngine;
using Yarn;

public class YarnTest : MonoBehaviour
{
public DialogueRunner dr;
public YarnProgram scriptToLoad;
private void Start()
{
//注入对话资源
dr.Add(scriptToLoad);
}

private void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
print("开始对话");
//开始一个对话
dr.StartDialogue("cc");
}
}
}

默认

使用自定义方法

我现在希望我第一次与角色交流时输出前2句,之后每次与角色交流只输出最后2句,这是一个游戏中常用的机制。但现在我们的对话只是按照流程依次执行,我们希望这个流程应该是能够动态控制的。
我们修改上面的yarn为:

1
2
3
4
5
6
7
8
9
10
11
12
13
title: cc
tags:
colorID: 0
position: 1,-22
---
<<if visited("cc") is false>>
Fasty97: Hi
PC: 你好?!
<<else>>
Fasty97: 我又回来了!
PC: 是忘了什么东西吗?
<<endif>>
===

可以看到这次我们使用 类似if语句的东西? 这是yarn中提供的一种语法模式,在这里我们会执行一个自定义的方法visted并将”cc”传入方法中,如果返回的结果是 false就执行下面的语句块。

处理自定义事件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
private HashSet<string> visitedNodes=new HashSet<string>();    //已使用节点
private void Start()
{
//注入对话资源
dr.Add(scriptToLoad);
//注入处理方法
dr.AddFunction("visited",1,(Value[] parameters) =>
{
var nodeName = parameters[0];
return visitedNodes.Contains(nodeName.AsString);
});
//绑定事件
dr.onNodeComplete.AddListener((name) => { visitedNodes.Add(name); });

}

创建一个HashSet集合用于存放所有已经被使用过的node,绑定一个onNodeComplete事件,这个事件有系统自动调用,在实现中为集合加入元素。
然后注入一个方法,第一个参数指定方法名(在yarn文件下的名称),第二个参数指定参数个数,第三个参数就是写入一个方法了,在方法中我们检查集合是否已经包含该值返回结果,一个自定义不可重复方法就处理好了。

visited效果

使用相同的方法你还可以创建各种各样的方法在yarn中使用。
值得注意的是:
通过源代码我们可以知道,yarn只支持以下几种数据类型。

1
2
3
4
5
6
7
8
case Value.Type.Number:
return (object) this.NumberValue;
case Value.Type.String:
return (object) this.StringValue;
case Value.Type.Bool:
return (object) this.BoolValue;
case Value.Type.Null:
return (object) null;

相关链接

YarnSpinner 官网
YarnSpinner 在线编辑器
YarnSpinner github