分支剧情创作中的挑战和工具

作者:icue
2021-07-22
49 57 17

在制作游戏时,我们常遇见一种四个字就能概括的问题:分支剧情。它构想起来并不困难,无论是脑海中、纸面上还是电子屏幕上,我们都能顺其自然地画出剧情流程图。然而待具体实现时,这简单的几个字下却隐藏着诸多挑战——要以何种方式创作分支剧情,才能把它转变成游戏引擎,或者说机器能够理解的媒介?

困难究竟在哪

如果把刚才这个问题中的“分支”两个字去掉,它仿佛就变得不那么棘手了。最显而易见的办法,无非是把所有的“在某件事发生之后触发哪个新的事件”、“谁在何时说了一句什么话”等等直接写到游戏本身的逻辑里去。虽然这个方法到头来会让剧情变得较难维护、对本地化不友好,但起码它直白、可行。

那么现在我们把“分支”两个字加回来。最直接的办法其实仍然存在——条件语句嘛。在现有的代码里,加上一个“取决于主角是否已完成某个任务,走向 A 剧情或者 B 剧情”不难吧?毕竟“完成过某个任务”是应该很容易拿到的一个、本身就会因为其它理由而存在的数据——等一下,如果是没那么唾手可得的信息呢?

如果剧情的分支需要取决于“主角是否与某名 NPC 有过交流”呢?这个信息听起来并不像是本来就会被记录的那种。办法还是有——记录下来嘛。每次主角与任何 NPC 交流,都在 Gameplay 逻辑中,额外地在游戏的数据库里标记一下。现在,可想而知,由于剧情走向难免会取决于各种信息,我们经常需要在 Gameplay 逻辑中记录和管理杂七杂八的、可能只服务于剧情的状态。

然而,当蜿蜒曲折的剧情发展到后期,即便我们做到了管理各种状态,条件语句也会变得越来越臃肿。这么做同时带来了更严重、也是刚才一直被逃避的问题:Gameplay 逻辑和叙事逻辑被混在一起,使得调试、排查和维护任何一边都变得愈发困难。某一段剧情没有按照预想的方式被触发,可能是因为此刻鼠标的点击没有被监听到,也可能是因为剧情上的触发条件没有写完备——到了这一步,开发只会越来越低效。

所以我们的问题变成了:如何既在叙事中安插分支,又将 Gameplay 逻辑与叙事逻辑尽量解耦,保证两边的思路各自清晰。

况且,刚才的分析都建立在了一个隐形的条件上——(对于作家和程序分开的团队来说)为游戏创作剧本的作家也得花时间和精力学习游戏引擎和代码,不然就得让程序员特地将剧情逻辑“复制”进游戏代码当中去。怎么选都不是什么优雅的方案,所以我们更加需要设法解耦,让写故事的人和写程序的人互不干扰,各自最大效率地产出内容。

常见解决方案

其实有些读者读到这儿,在脑海中应该能预想出一个解决方案了。说白了,我们需要的是一个独立于游戏引擎,但又比日常的文本编辑器强大的剧情编辑工具。它起码得对作家友好、能设计分支剧情、跟踪状态,以 Gameplay 逻辑为辅而不是为主,并生成能被游戏引擎识别的内容

幸运的是,这个问题早已被许多游戏开发者意识到了,也因此涌现出不少插件、工具和叙事引擎。我在这里介绍几款较为主流的,它们的使用场景有重叠,但也有不同。需要额外指出的是,针对 Galgame 以及类型相似的文字冒险游戏,已有较为成熟的游戏引擎,本文探讨的诸如分支流程等问题已经被那些引擎自然而然地解决了。所以,接下来要介绍的这些工具,是应用于非文字冒险、但又涉及到分支剧情/对话的那些游戏的。《极乐迪斯科(Disco Elysium)》?《霓虹出租(Neo Cab)》?《林中之夜(Night in the Woods)》?是,就是那些风格。事实上,这几个游戏全都使用了这些工具中的某一个。

限于篇幅,我不能对这些工具深入展开,希望简短的介绍起码能讲清楚它们各自是什么。至于具体怎么用,我会在小标题链接到官网,那里通常配有技术文档帮助上手。

Twine

Twine 链接地址

Twine 是一个开源的基于网页的分支剧情创作器。

Twine

每个剧情节点内都包含了一段文字剧情,节点之间的箭头使流向变得直观,分叉处也显而易见

从未写过代码的人可以迅速上手,而对于有编程经验的人来说,Twine 也提供了语法来实现赋值变量、条件控制(某些选项只有满足特定条件才会可选)等。

Twine 可以在线使用也可以下载客户端。撰写剧本的过程中可以随时从指定节点起“试玩”接下来的剧情,游玩的过程即用鼠标在网页上点击选项,剧情会按照设计好的路线来推进。这听起来很简陋,但这可能是迅速创建一个可玩的互动电子剧本的最快方法了,所以适合迅速搭建原型。

在 itch.io 上有近 6000 个使用 Twine 制作的游戏,这庞大的数量也得益于 itch.io 对网页游戏的支持——Twine 可以直接生成网页游戏,但不能生成被其他游戏引擎读取的数据文件。有一个叫做 Cradle 的插件可将 Twine 生成的故事导入 Unity,但该插件已不再维护,随着 Twine 自身的更新迭代,我并不推荐去研究 Cradle 。如果对 Twine 的操作模式和功能感到满意,但又不满足于只在网页上游玩、想要和游戏引擎深度集成,那么接下来的 Yarn 是更好的选择。

Yarn

Yarn 链接地址

Yarn 开源,基于 Twine,正如它们两个词的意思本身也很像。

Yarn 的编辑器,但是也可以选择不借助流程图,使用文本编辑器

Yarn 的设计者之一 Jon Manning 曾在一个讲座上提到过他们的理念:让作家不需要学写代码,但允许作家通过 Yarn 来实现代码能够实现的事。所以,和 Twine 类似地, Yarn 定义了一套非常简洁的脚本语言,来实现条件判断、变量追踪等。不同的是 Yarn 可以配合 YarnSpinner 使用,将整个剧情逻辑导入 Unity(所以在 Unity 的 Gameplay 逻辑里可以一键“进行到下一段剧情”),甚至可以在 Unity 中定义函数,在使用 Yarn 编写剧情的过程中调用它们。

但 Yarn 自身不支持预览剧情,我的理解是,这意味着只有在导入 Unity 并完成相关的读取逻辑以后,才能在 Unity 中试玩到使用 Yarn 创作的剧情。这是 Yarn 目前比较大的一个短板。

从官网可知 Yarn 对本地化的支持不错。著名的借助 Yarn 完成的游戏有《林中之夜(Night in the Woods)》(正是该制作组带来了 Yarn)、《短途旅行(A Short Hike)》

ink

ink 链接地址

如果说 Yarn 兼顾了视觉上流程图的直观性和逻辑上脚本语言的灵活性,那么 ink 可以说是在灵活性上走向了极致——这个工具不提供流程图,因为剧本片段之间的关系太过千变万化。

inky

ink 的编辑器 inky,左边进行剧情编写,右边则是实时试玩

ink 是带来了《80 天(80 Days)》《天堂之穹(Heaven's Vault)》等作品的 inkle 工作室开发并开源的一个脚本语言。主创之一 Jon Ingold 曾不止一次说过他并不喜欢所谓“流程图”的概念,因为流程图本身的存在,就意味着节点有固定的先后顺序

A flowchart says this blob exists within a structure, where this comes before and this comes after. In Heaven’s Vault, when Six and Aliya walk around, there’s a bucket of about 3,000 to 4,000 things they can say.

And Ink just runs through all of them and says, ‘give me all the conversations that would make sense at this moment’. And then it says, ‘which one is the most relevant to what you were talking about last’, and it puts that in front of the player. And that’s all it does, there is no structure, no flowchart.

通过 Jon 的这段描述,我们不难理解 inkle 从不依赖流程图。如果某个角色接下来要说的话有三千种可能性,而这三千个备选项也能存在于不同流程里更早或更晚的对话中,那么我们需要的显然不是流程图,而是一个筛选器,挑选出最符合当下语境的那一句,然后推进剧情。而被选出来的那一句话,在下一次相似语境中就不会再被选中。

不仅对话,在 inkle 的设计理念中,剧情片段也是一样的道理。接下来要发生哪段剧情,与上一段发生的是哪段剧情并非强相关,更多地,系统会考量自游戏开始后的各种状态、玩家的历史选择——ink 默认会记住玩家作过的每一个选择,包括很久以前的,而不需要我们手动使用变量去跟踪——从整个剧情池中挑出一个来推进剧情。

当然,ink 仍然支持之前 Twine 和 Yarn 支持的那种传统分支结构,只是在这里一切都需要靠脚本语言去编写,不再有流程图了。

摆脱了流程图的束缚,ink 可以实现相当细腻的“响应式(responsive)文字”。

GDC ink

GDC 幻灯片截图(文末有链接)——上为 ink 中的一段,下为编译后众多可能结果中的两个

在这个例子里,短短的一段文字,经过随机短语间的排列组合,取决于玩家是否穿着潮湿的衣服、当前地形是否为树林,便能有好几十种最终的呈现方式,底下的两段只是其中的两种。若这样精细的内容调整贯穿整个剧本,那流程图当然难以体现密密麻麻的走向可能性。

也正是因为没有流程图,一旦学习了 ink 的语法,写剧本的效率要高于其他工具——毕竟不必每次想添加一段剧情,都先用鼠标在流程图上新建一个节点了。在这里,就像传统写作那样,手指不必离开键盘,一直打字就行。

ink 官方提供了 Unity 插件,民间则有虚幻、Godot、GameMaker Studio 2 的插件。可惜 ink 对本地化的支持不好,用一种语言写完的剧本,若想要翻译,那么剧本里的可变部分(也就是那些响应式的部分)越多,翻译过程就越艰难,如果跨语系就更加如此。

ink 也不只适用于文字为主的游戏。作为一个免费的开源工具,怎么用完全看需求。像《霓虹出租(Neo Cab)》Sable这类音画占比也很大的游戏,也都使用了 ink。

articy:draft

articy:draft 链接地址

方才的 ink 在写作过程中可以说是面向过程的,而接下来的 articy:draft 则能满足面向对象的设计——等一下,写互动剧本也能面向对象吗?这不是计算机领域的词汇吗?

游戏开发的本质仍然是程序开发,当然可以面向对象。就拿主角的一句台词来说,一句台词包含什么?

倘若我们能想到的只有人物和台词这两个属性,那还是没有跳出传统写作的框架。试想,在各种需求下,显示这句话的文字颜色、人物表情的不同立绘、语音播放这句台词所需的时间长度、这句台词在选项菜单里显示的缩略文字(因为可能显示不下完整的台词)等等等等,都是游戏里可以被绑定在“台词”身上的属性。

而人物的属性就不言自明了,等级、职业、血量……从这个角度出发,我们的确可以面向对象地先定义每句台词、每个人物的属性,设置默认值,进而在创作剧本时系统性地照顾到它作为“游戏剧本”的方方面面。

而 articy:draft 天然地支持往对话和人物上添加自定义属性、设置类型和默认值。一旦属性设置完毕,就能在流程图的各个地方去引用和修改。用户也可以自己定义新的 Entity,例如“武器”,设置武器的各个属性,并在 articy:draft 而不是游戏引擎内新建多把武器。接着就可以往人物里新增一个“武器”栏位,代表人物目前持有的武器,而这一切信息都将在游戏引擎内被读取——这进一步说明 articy:draft 适合面向对象的创作思路。

articy:draft 的分支对话流程图

在 articy:draft 的流程图中,每个节点可以是一段剧情或是一句台词,通过条件、指令等串联。articy:draft 支持节点的无限嵌套,这对管理具有从属关系的剧情片段非常有帮助;合理安排层级关系,那么剧情流程图从外到内就能井井有条。articy:draft 自带一个数据库管理的面板,可定义全局变量,在流程图中读取和赋值;在预览故事流程时,还能实时查看每个变量的值。

配合刚才提到过的“在流程图内引用和修改人物属性”、“在 articy:draft 里管理人物配备的武器”,不难发现 articy:draft 其实已经可以在剧情逻辑里实现相当一部分 Gameplay 逻辑了。如此一来,一个作家不需要掌握游戏引擎也能在撰写剧情的同时包揽一些 Gameplay 逻辑。当然,这是否可取就见仁见智了。

articy:draft 支持本地化、配音、版本管理和多人协作,官方还提供了 Unity 和虚幻的插件。其实 articy:draft 能做的不仅仅是分支剧情的管理,它还能管理游戏设计文档、剧本大纲、游戏地图等,但这些方面我了解得不多,也不是本文讨论的重点,故不再展开。

有不少互动小说使用了 articy:draft,如《极乐迪斯科(Disco Elysium)》《奥威尔(Orwell: Keeping an Eye On You)》《骇游侠探(Gamedec)》等。在官网可以找到相关游戏各自的访谈

不同于之前的几个工具,articy:draft 是收费的,好在 Steam 上打完折也不是很贵。一些大厂如 CDProjekt RED、Techland 也是 articy:draft 的客户,这么想,或许能让这钱花得更心安理得些。

其他方案

  • Chat Mapper:类似 articy:draft 但是订阅制,我了解不多。
  • Dialogue System:Unity 素材商店的强大素材,自身可用于编写节点式分支对话(但要注意,这等于还是要在 Unity 里进行剧本创作),也支持 ink、articy:draft、Chat Mapper 等的导入,将来也会支持 Yarn。
  • 自己实现工具:我相信对于资源丰富的大厂来说,都有成熟的内部工具来辅佐各种类型剧本的创作了。黑曜石就曾分享过他们的分支对话工具使用心得,同样是基于流程图的。而对于有闲功夫的独立游戏人,想自己造一个这样的工具出来玩,也值得鼓励——何况上边介绍到的许多开源产品都可以用作参考。

结语

让我们回顾一遍开头的问题:如何既在叙事中安插分支,又将 Gameplay 逻辑与叙事逻辑尽量解耦,保证两边的思路各自清晰?

回想介绍过的那些工具,除了不支持和游戏引擎结合、但适合快速在网页上搭建原型的 Twine 以外,其余都能满足这个要求。当然,刚开始都需要花时间学习工具本身的使用,以及如何和游戏引擎结合。另外,可以看到这些工具或多或少都支持从叙事流程中调用游戏引擎里 Gameplay 相关的函数——如何划清叙事逻辑与 Gameplay 逻辑的界线也是我没能展开讨论的话题,但我认为这个问题没有标准答案,很大程度上取决于游戏本身的性质、甚至创作人员对两边工具的熟悉程度。总之,工欲善其事必先利其器,一旦上手,之后的剧本创作和游戏开发将齐头并进、不再混沌。

每个工具的设计理念不尽相同,这些简短的介绍只是一个引子;究竟哪个适合自己,还得留给读者自行考察与斟酌。即便没有迫切需求,也希望对这些工具的探讨能触发大家对分支叙事实现方式和应用场景的思考。

扩展阅读

近期点赞的会员

 分享这篇文章

您可能还会对这些文章感兴趣

参与此文章的讨论

  1. sdj大傻 2021-07-22

    感谢分享,我试试ink去,建卡片可烦人了

  2. 无有时代 2021-07-25

    哈哈哈我也是写互动剧本的,但到目前为止,用的最多还是纸+word,希望中文也有类似好用的工具?不过印象中好像已经有了吧

    • icue 2021-07-25

      @无有时代:文中提到的这些应该都是支持中文的

    • 决斗者俱乐部 2021-07-26

      @icue:我尝试了一下,ink的节点标题和关键变量不能用中文否则会报错。twine因为说yarn是升级版我试用了yarn(还没放进unity调试过),yarn在线版是支持中文的,看界面也有中文所以支持应该不错。

  3. 无有时代 2021-07-25

    如何既在叙事中安插分支,又将 Gameplay 逻辑与叙事逻辑尽量解耦,保证两边的思路各自清晰?

    这个问题确实很难啊,只能在实践中慢慢摸索了

  4. 决斗者俱乐部 2021-07-26

    总结一下:
    twine和yarn:免费开源中文支持不错还有在线版。卡片流程图思维,但似乎没有复杂的文件管理功能。yarn具有本地化文本对比插件(必须在unity中使用),调试也必须在unity中。
    ink:纯净的互动文本编辑器,无中文(非西语都没有)支持,虽然文本本身能用中文写,但是节点标题和关键函数必须用英文否则报错。因为过于纯净所以没有任何文档管理,但可以直接在编辑器内调试整个流程。
    articy:draft:下载了试用版,感觉学习成本比较高,但是看了教程基本能懂的程度,基本相当于一个脚本蓝图。有其他信息,文件夹和图片资源款里,可视化。因为太复杂没有仔细看有没有本地化管理(应该会有吧)。
    看导出方式,基本上就是json一类。
    我现在在做的游戏就是我和partner一起徒手写的unity脚本导入函数,wps画流程图,用word撰写剧本,用excel编辑器管理,函数参数也是自己想设几个就设几个的,整体也不难而且自由度非常高。但这些软件可贵在:1)作者不一定懂程序和untiy。2)大量文本脚本的管理以及团队协作开发。3)可能有本地化插件支持。

    用一个网络笑话来讲,就是:做什么工作都离不开office全家桶!

    经常写作的朋友可能会了解ulysess,scrivener还有final draft这几个软件。我自己在用前两个写小说(其实我们游戏的word脚本文档也是用ulysess写好后导出的方便没有mac的人看)。
    在我看来,ink的概念接近ulysess,articy:draft的概念接近scrivener,yarn我目前感觉是升级版的WPS。

    ink/ulysess的概念是碎片化写作,tag式管理,随意组合拼贴,高自由度,对写作者来说十分沉浸高效,有即时反馈机制所见即所得。盲点就是它适合写作经验丰富、脑内逻辑清晰的作者型写作者,最好有一定的程序(至少是脚本语言)基础。我个人是这个类型,所以非常理解80days那个作者说的,讨厌卡片和过于死板的流程图。而这种工具也更适合以文本主导的项目,同时支持涌现式剧情呈现。
    articy/scrivener的概念是全资源管理,RPG式写作,面向对象,上手难度高,逻辑和归纳性强,大型工程管理软件。盲点是缺少一定自由度,不够沉浸。不一定需要有程序思维,但是必须有RPG思维,懂流程蓝图为佳。目前我还没有做这种体量的项目所以体会不到它的好处,它目前的上手难度和界面难看程度以及过高的定价阻止了我使用它。同理scrivener我在写那种20人以上的多部长篇的时候会用到,一般时候中短篇用ulysess足矣。

    • icue 2021-07-27

      @决斗者俱乐部:流程图那块儿,可以试试miro(miro.com),支持多人协作,胜任流程图的同时也提供了丰富的模板,像项目管理、进度跟踪、待办事项之类用的多种图表都有,也都很漂亮。但我是一个人用,超过一个人可能要收费。
      Scrivener我以前写小说的时候也用过,非常喜欢,尤其是它那个在一个随时可见的小窗口里记录随想的功能。总之我觉得,工具对每个人或者团队来说,不求完美,底线是不拖慢正常的开发速度吧

    • 决斗者俱乐部 2021-07-27

      @icue:我现在协作用notion,项目管理的功能差不多,不过没有流程图(貌似),所以流程图的话就wps解决了,因为策划暂时就我一个所以我画好导成图片或者用分享链接贴到notion里面就行。
      u1s1还是那句话,生产力工具其实也只是个辅助,90%的问题office就能解决o(*≧▽≦)ツ

  5. icue 2022-04-05

    今天 articy:draft 发布了免费版,支持商业用途,只是在 objects 数量上有 660 个的限制。
    详见 https://www.articy.com/en/articydraft/free/

  6. 最後 2022-08-26

    articy:draft在steam上有卖,可以直接买断个人版,价格也还合理,跟订阅版的比起来就是缺少多人协作功能,但其实自己本地搭建服务器的话也能间接实现多人协作,用起来还是不错的。

    最近由 最後 修改于:2022-08-26 17:30:51
  7. yanruye 2022-09-30

    研究了一下ink,确实轻巧优雅,但没搞懂「系统会考量自游戏开始后的各种状态、玩家的历史选择从整个剧情池中挑出一个来推进剧情」这种storylet模式要怎么实现
    在ink中只要knot/choice结尾没有divert就会报错说loose end,非得跳转/收束到下一个明确的节点才行,说到底这跟twine一类的有啥本质区别呢?

    最近由 yanruye 修改于:2022-09-30 18:27:17
    • icue 2022-09-30

      @yanruye:divert 是可以放在 if/else/switch block 里的,见:https://github.com/inkle/ink/blob/master/Documentation/WritingWithInk.md#example-context-relevant-content
      也就是说可以做到:如果满足 X,去A;如果满足 Y,去 B……或者更复杂的逻辑。当然你可以直接在 Issues 里提问关于 storylet 的实现有没有更系统化的办法,和开发者直接交流。

      和 Twine 的区别,我觉得两个使用场景不一样,Twine 的成品就是一个网页上可以玩的交互式小说,而 ink 可以接入许多游戏引擎,而且从 GitHub 上的教程长度也可以看出来,它的整套语言,算上 function 之类的,其实已经很复杂了,可以实现许多功能。

      再多说一句,Yarn Spinner 2.2 版本已经长得很像 ink 的编辑器了(https://twitter.com/YarnSpinnerTool/status/1547827479871897601 ),感觉这两款工具在使用场景上正在靠拢……

      最近由 icue 修改于:2022-09-30 21:03:39
  8. yanruye 2022-09-30

    @icue:我原本主要使用的是articy,看到说「ink尤其适合storylet」所以想试试,但体验下来感觉对storylet也没什么特别的支持?

    • icue 2022-10-01

      @yanruye:我是看到 inkle 工作室出品的游戏大都符合 storylet 的叙事模式,所以推断用 ink 来做 storylet 一定不会有太大的阻碍,而且 ink 写起来比较轻便,感觉会更适合长时间沉浸式写作。
      我自己也在用 articy,storylet 在 articy 里的确可行(虽然按我目前自己的摸索是需要把它和游戏引擎紧密结合才能实现),总之感觉比 ink 更加规整吧,前期准备工作会多一些,写的时候也可能被 UI 稍稍拖慢效率。

    • yanruye 2022-10-01

      @icue:非常感谢您在分支叙事上的研究,给了本人很大的启发!期待能看到更多的产出~

  9. cyanlink 2023-11-21

    yarn 已经迁移了,现在整个项目都叫Yarn Spinner了,我觉得如果是熟悉ink的同学,但是又希望有更好的本地化翻译支持,yarn spinner是不二之选。Yarn Spinner基本上就是Renpy味的Ink脚本(分支、跳转、tag和metadata是ink,调用函数、演出指令等是renpy),但Renpy和Fungus都是那种专门为了视觉小说提供了一大套功能的系统,耦合较为紧密,不适合拿来扩展和我们程序交互。Inkle那个编辑器已经基本不更新了,停留在很老的Node版本,有很多bug,而且中文显示也有问题,Yarn现在用的是VSCode插件,整个设计理念和界面都非常先进!

    • π 2023-11-25

      @cyanlink:嗯有启发+同意
      前几个月也刚在这个文章的基础上做了些拓展调研,感觉Yarn现在基本多数情况下都是一个很好的选择了

您需要登录或者注册后才能发表评论

登录/注册