故事和显着性入门

当你做正确的事情时,人们不会确定你是否做了任何事情。 - 飞出个未来

介绍

小故事和显着性代表了交互式讲故事技术的演变。为了理解它们的重要性,让我们来看看叙事方法是如何随着时间的推移而发展的。

[!信息] 这里和纱线纺纱机中使用的许多术语都是基于 艾米丽·肖特 (2019), 和 Kreminksi 和 Wardrip-Fruin (2018),这些都是关于该主题的优质资源,请阅读它们。

互动讲故事的演变

线性叙事

最早的讲故事方法是线性的。故事遵循作者定义的单一路径,每个时刻都经过精心设计,直接通向下一个时刻。

线性故事

分支叙事

下一个演变引入了分支,让故事有多种路径供玩家探索。

分支故事

分支叙事提供了显着的灵活性。有些分支可能很广泛,具有重大影响,而另一些分支可能很小,增加了微妙的味道。有些路径可能会终止,而另一些路径可能会重新连接到主要故事情节。尽管具有这种灵活性,但每个步骤仍然是作者精心设计的,分支按照作者的预期顺序固定。

[!信息] 如果您想对分支叙事中一些最常见的形状和模式进行详细分析,请查看 阿什韦尔海角 (2015).

基于故事的叙事

小故事代表了这一演变的下一步。它们打破了叙事元素之间的僵化联系,创造了更加动态的流程。理论上,一个故事可以从任何小故事移动到任何其他小故事,从而在每个块到每个其他块之间创建潜在的连接。

自由形式的故事

理解显着性

如果叙事块是互不相关的,它们如何形成连贯的体验?这就是显着性的用武之地——它将故事片段链接在一起的机制。

[!信息] 更准确地说,显着性是 Yarn Spinner 执行此操作的方式。还有其他方法,最简单的是“呈现所有内容并让玩家选择下一块”。

显着性决定了在任何给定时刻哪个故事情节最相关(或“显着”)。显着性不是作者定义的序列,而是动态选择顺序。例如,如果您有两个故事 - 一个关于进入公寓中的任何房间,另一个专门关于进入卧室 - 当玩家在卧室中时,更具体的故事会更加突出。

有趣的是,线性和分支叙事可以被视为由小故事组成的显着故事,其中最显着的小故事是由作者的明确联系定义的。这种观点凸显了小故事的主要优势:它们可以合并和融合以前的结构方法。这可以让您在需要时进行精确控制,同时保持动态叙事进展的灵活性。

结合线性、分支和故事情节

[!信息] 您可能会“等等,这听起来很像 [经典游戏] 所做的,我真的很喜欢很久以前的游戏!?”你是对的,它非常相似。这些想法并不新鲜,这些概念的演变也不像我们在这里暗示的那样离散。

故事粒度

The fundamental particles, including the Storylet. Modified image from Wikipedia

小故事是这个叙事系统的基本单位,但小故事应该有多大或多小呢?答案取决于您的具体叙述需求。

Storylet 通常存在三个粒度级别:

  1. 集合级别:最大的单元 - 一个小插图、对话或段落。在这个层面上,你的故事是通过连接独立的时刻来组装的。这些矩通常独立发挥作用,因此它们的精确顺序可能是灵活的,或者它们可能被设计为与其他矩的子集自然流动。
  2. 台词级别:在这里,一个故事集代表一行对话。对话是通过组合单独的台词来建立的,然后形成更大的叙事时刻。这种方法对于在游戏中创建动态 NPC 吠叫特别有效。
  3. 子线级别:最小的单元,其中故事是单线内的片段。这些片段结合起来形成完整的对话线,然后组合成对话。

许多游戏融合了这些方法,通常将故事技术与传统的线性或分支内容混合在一起。不要只关注故事的大小,而是考虑您想要创建什么类型的叙事体验,并确定什么级别的故事粒度最能支持该愿景。

显着性的类型

我们如何确定接下来“最好”呈现哪个故事?该方法根据您的叙述目标而有所不同。

基于质量的显着性

最常见的方法是在每个故事中使用条件 - 布尔表达式,例如“我们在卧室吗?”或“玩家是否有超过 25 个金币?”这些条件会过滤可用的故事并帮助在剩余选项中进行选择。当多个故事情节有效时,您可以选择“质量”最高的故事情节——通常是满足最多条件的故事情节。

基于标签的显着性

另一种方法是用不同的属性来标记故事。选择下一个故事时,您可以根据相关标签进行过滤。过滤标准可能直接来自玩家的选择或引导叙述的系统。

定向显着性

有些方法旨在引导叙述走向特定的结果:

简单的显着性方法

两种不太复杂但仍然有用的方法包括:

  • 玩家选择:呈现所有可用的故事情节并让玩家选择。
  • 随机选择:从可用的故事中随机选择。

这些方法通常结合剔除或取消优先级系统来防止重复。当多个故事具有相同的显着性时,它们还可以有效地解决歧义。

实践中的故事

Storylet 在游戏中具有多种叙事功能:

NPC 吠叫

也许最常见的用途是创建上下文 NPC 评论。 《天际》中臭名昭著的“膝盖之箭”台词就体现了这一点——当玩家清除地牢时触发,这是大多数玩家最终满足的条件。

环保风味

小故事创造了特定的时刻,为游戏世界增添了活力,而无需直接连接到主要情节。 《质量效应》的电梯对话根据您当前的小队成员进行过滤,演示了这种方法。

情境反应

Storylet 可以创建针对游戏时刻的高度具体的对话,使 NPC 看起来更有意识、更具反应性。 《Left 4 Dead》中的战斗和停机时的吠叫就体现了这一点,《最后生还者》中艾莉的情境反应也是如此。

涌现叙事

在没有预定故事的游戏中,小故事会创造有意义的时刻和旁白。 《文明 VII》使用历史故事和替代历史事件,由文明类型、领导者和当前玩家行为等因素触发。

可探索的叙事

数据库驱动的游戏使用故事让玩家自由探索叙事空间。她的故事体现了这种方法,其独立的故事块既独立又有助于整体叙事。

完整的叙事系统

有些游戏根据故事构建完整的叙事。 《玫瑰面具》和《荒野神话》完全由基于玩家行为的小故事组成故事,让玩家能够创造自己独特的叙事。

[!信息] 许多游戏都没有谈论他们使用故事的方法,但使用本指南中已有的术语来谈论它比使用开发者自己所说的每个游戏都不同的术语要容易得多。

纺纱工的故事

Yarn Spinner 支持两个主要级别的故事粒度:基于行和基于节点。两者都与传统的分支和线性 Yarn 脚本无缝集成。

线路组

线路组实现线路级别的故事。它们在视觉上类似于选项组,但使用 => 而不是 ->。组中的每一行代表一个潜在的故事情节,但只会选择一个。

Barry: Oh is that so?
 
=> Alice: Yep.
=> Alice: Of course it is!
=> Alice: Why would you think otherwise?

对话系统接收巴里的台词,然后接收来自爱丽丝的选定台词。玩家可能会看到:

Barry: Oh is that so?
Alice: Of course it is!

系统并不表明爱丽丝台词来自故事片段选择,它只是简单地呈现为下一行对话。

我们可以添加条件来修改选择:

Barry: Oh is that so?
 
=> Alice: Yep.
=> Alice: Of course it is! <<if $barry_suspicion > 3>>
=> Alice: Why would you think otherwise? <<if $barry_suspicion > 5>>
=> Alice: I am not talking without my lawyer <<if $barry_suspicion > 5 && $knows_barry_is_cop>>

假设巴里高度怀疑并知道他是警察,对话可能会呈现:

Barry: Oh is that so?
Alice: I am not talking without my lawyer

即使有多个选项满足其条件,最后一行仍被选为最显着的选项。

与选项组一样,行组支持仅在选择特定行时才显示的嵌套内容:

Barry: Oh is that so?
 
=> Alice: Yep.
    Barry: lol lmao, thanks nerd.
=> Alice: Of course it is! <<if $barry_suspicion > 3>>
=> Alice: Why would you think otherwise? <<if $barry_suspicion > 5>>
=> Alice: I am not talking without my lawyer <<if $barry_suspicion > 5 && $knows_barry_is_cop>>
    Barry: Why would you need a lawyer?
    Alice: *cool silence*

任何 Yarn 对话或命令都可以嵌套,包括其他故事、跳跃和绕道。

节点组

节点组允许关联更大的故事块。它们看起来像标准节点,但需要 when 标头:

title: Barry
---
Barry: Oh is that so?
<<jump Alice>>
===
 
title: Alice
when: always
---
Alice: Yep.
Barry: lol lmao, thanks nerd.
===
 
title: Alice
when: $barry_suspicion > 3
---
Alice: Of course it is!
===
 
title: Alice
when: $barry_suspicion > 5
---
Alice: Why would you think otherwise?
===
 
title: Alice
when: $barry_suspicion > 5
when: $knows_barry_is_cop
---
Alice: I am not talking without my lawyer
Barry: Why would you need a lawyer?
Alice: *cool silence*
===

什么时候 <<jump Alice>> 执行时,它会跳转到“Alice”组中最显着的节点。如果巴里高度怀疑并且爱丽丝知道他是警察,系统会选择最后一个节点。

对于这个简单的示例,节点组需要比线组更多的写入才能达到相同的效果。然而,对于具有显着变化的较大对话,节点组变得更有利。

[!信息] 您可能会注意到,您可以拥有尽可能多的 when 节点 Storylet 上的标题。您可能还会注意到 when: always 其中一个故事的标题,这是节点组所必需的,以表示“这个始终可用”。

与线路组一样,节点组可以包含任何有效的 Yarn 内容,包括跳转、绕行和线路组。

显着性策略

对话运行器在呈现故事时会参考显着性策略,无论是来自行组还是节点组。虽然您可以创建自定义策略来实施任何方法,但 Yarn Spinner 提供了几种内置的基于质量的策略:

  • 最佳(选择最突出的)
  • 最近最少查看的内容(优先考虑最近未查看的显着内容)
  • 随机最近最少查看的内容(如上所示,进行一些随机化)
  • 随机(完全随机选择)

所有内置策略首先会过滤掉具有失败条件的故事,但如果需要,自定义策略可以包括失败条件。

建议的默认值是随机最近最少查看的内容,它可以平衡最高显着性内容的选择,同时防止重复。