互动写作的挑战:设计像《神秘潮汐》这样的非线性 RPG

CHRISTOFFER BODEGÅRD / SUDDEN SNAILGame Developer and Writer
Mar 17, 2026|7 Min
Christoffer Bodegård的《神秘潮汐》的封面艺术 | Made with Unity。身穿蓝色长袍的冒险者向背对着摄像头的骷髅战士挥舞着一把断剑。身穿粉色长袍的哥布林在红色巨龙的陪同下,忧心忡忡地观望。游戏《神秘潮汐》的标题位于左侧。
为方便起见,此网页已进行机器翻译。我们无法保证翻译内容的准确性或可靠性。如果您对翻译内容的准确性有疑问,请参阅此网页的官方英文版本。

神秘潮汐 正在席卷 Steam – 但像这样的分支叙事 CRPG 是如何制作出来的?在这次客座博客中,Christoffer Bodegård 解读了复杂的叙事设计决策,以及他八年学习如何管理真正非线性的对话式故事创作的历程。

自首次公开游戏测试以来 神秘潮汐 早在 2023 年,我就被反复问到一个简单的问题:“如何跟踪所有内容?”这是一个很好的问题——一个很难的问题。多年来,我可能以几种不同的方式回答了这个问题,但从未真正满意过……所以让我们试一试。

(但首先,先简单介绍一下 Esoteric Ebb)

神秘潮汐 是一款宏大、注重叙事、非线性的 CRPG。没有传统的战斗,几乎完全基于对话,游戏时长在45分钟到50小时之间,还有很多选择……真正的选择,会从根本上改变你体验的选择,直到结束。是的,它就是 这类 游戏之一。制作这个项目花了很长时间:从开始到完成大约花了八年,其中一半的时间什么都不做,独自坐在房间里,学习如何进行 互动写作.

互动写作的三个限制条件

我将互动写作定义为三个较为任意的限制条件/目标。这些包括:

  • 高选择与文本比率
  • >50%的内容为动态内容
  • 开放式设计

你可以随意选择或忽略这些,但如果你实现了这三点,那么你就找到了激发(潜在)积极用户代理的秘诀。但一看到这个,你可能会遇到几千个问题。

让我们一一分析。

The pale man holds incredible power, if he is able to bypass the esoteric limitation. #int #DC10
"However, I suggest you speak with Lady Sageleaf about this, if you require answers. I am simply a middle-man in this." #Visken
-(riverHub)

	+.Snell==1-"Snell." \(Look at him.\)
		The goblin gives you a conflicted expression. #Snell
		"I... didn't know, Cleric. I really didn't." #Snell
		"He did not." #Visken
		"Lady Sageleaf instructed me to not inform anyone. Even her own agents." #Visken
		"No need to be paranoid." #Visken
		
			++"How can I not be paranoid? Everyone's lying to me!"
				"Correction: I was lying to you. Lady Sageleaf, potentially as well." #Visken
				
			++"True. It's just some esoteric bullshit."
				"...Indeed." #Visken
		--
		Snell scratches his chin. #Snell
		"I'm not entirely sure how to feel about this." #Snell
		"The Old Lady isn't one to spend money on resurrecting a city cleric." #Snell
		"But I'm guessing she didn't want to wait for another one to appear?" #Snell
		"Hm. We should go speak with her. But... remember that she paid for your resurrection, Cleric." #Snell
		
			++"That is true. She seemed nice enough."
				"...I wouldn't use 'nice'. But she's at least very, very competent." #Snell
			
			++"I'll refrain from commenting until I hear her side of it."
				"Smart." #Snell
				
			++"I'm not sure I believe you."
				"That's okay." #Snell
				"But really, I'm not sure what I would gain by lying about this." #Snell
		--
		The goblin is telling the truth. You can read it in his eyes. #wis #DC14
		It was a LIE. But it was a LIE for <b>expediency</b>... #con #DC9

	+"What spell did you use to revive me?"
		He is quiet for several seconds. #Visken
		Considering if he should share this knowledge. #wis #DC13
		A modification, then. #int #DC12
		A <i>personal</i> resurrection spell. #reply #int
		"<i>Raise Dead</i>." #Visken
		"With changes. It is not the original spell, as I'm sure you understand." #Visken
		<i>Visken's Raise Dead</i>. #int #DC12
		"My spell requires a higher cost, while lowering the spell's complexity in return." #Visken
		
			++"A higher cost? Like... a blood-cost?"
				"No, Cleric." #Visken
				
			++"What do I owe you?"
				"Nothing. Lady Sageleaf offered to pay it in full." #Visken
				
			++"A higher crown cost?"
				"Yes, Cleric." #Visken
		--
		"The new cost is doubled. One thousand crowns." #Visken
		"Which is not too bad." #Visken
		
			++"My life is worth much more than that, yes."
			++"Eh. Could be better."
			++"Waste of money."
		--
		The pale man stares at you. #Visken
		
	+"Is this why I lost my ability to cast higher level spells?"
		"Potentially." #Visken
		"Whatever issues your body and soul appeared to have had with my spell, it was not permanent." #Visken
		
			++"Yeah, I've rebounded quickly."
				"Yes indeed." #Visken
				
			++"I'm just that awesome of a wizard, I guess." #.WIZARD+=1
				"Of course." #Visken
				
			++"My soul <i>and</i> body?"
				"It's more common than you might think." #Visken
	
	+"I felt really weird when I woke up. Like... different. Is that your dark magic also?"
		"That can happen, yes." #Visken
		"As it can with any resurrection magic when a soul is given sufficient time spent away from its body." #Visken
		
			++"So my soul is ruined?"
				"No." #Visken
			++"I like this new me."
				"Wonderful to hear." #Visken
			++"I don't think the difference was that big, honestly."
				"Good." #Visken
			++"Can I go back to my old self?"
				"No." #Visken
		--
		His cold voice shows no interest in your personal business. #wis #DC10
		Eh. Whatever changed, it was probably for the best. #dex #DC16
		Still got your wits about you. That's what matters. #reply #dex
		At least you are still highly intelligent. #int #FC8
		That is all that matters. #reply #int
		Soul magic is complicated. Not even the greatest Arcanists were able to unlock all of the secrets of the <i>inner light</i>. #int #DC15
		Perhaps one day, you will. #reply #int
	
	+"Right. I'll... go speak with Lady Sageleaf."
		"Good idea." #Visken
		The pale man was simply an instrument. #int #DC11
		But it is good to understand this game you've been entangled within. #reply #int
		->questions

-
->riverHub

通过文本比值优化玩家用户渗透

为什么文本比值高很重要

高选择与文本的比例听起来很棒。首先,这是一个让玩家保持清醒并保持参与的绝佳工具。如果你强迫他们阅读太多文本块,那么普通玩家的眼睛就会变得昏昏欲睡。但如果你不断地挑逗他们——强迫他们回答有趣的问题,逼迫他们做出艰难的决定,或者强迫他们回应粗鲁的指责——那么这就像向他们的血管中注射了能量饮料。他们会突然清醒过来,并真正地与文本互动。至少从统计上讲,他们更有可能这样做。

这里的问题很简单:你得 疯了 才想在对话中添加这么多的分支。这需要很多工作,更具体地说,它需要一套非常特定的工具。(当然也需要技能,但工具必须灵活且快速,否则分支过程就会变成一项耐力测试)。

Christoffer Bodegård的《神秘潮汐》截图 | Made with Unity。
《神秘潮汐》| Christoffer Bodegård

选择合适的工具

我使用的工具是宏伟而令人难以置信的奇妙 墨迹脚本 由 Inkle 工作室创建。通过开发这个开源工具(顺便说一下,它在Unity中运行完美),他们实际上改变了我的职业生涯。我欠他们很多。墨水是一种工具,除了它能做到的所有其他很酷的事情外,它非常适合快速灵活的分支。

当我用墨水编写对话时,我用与线性内容相同的速度写作。只要有一个松散的设计大纲,我就可以开始创作了。添加玩家表情、管理视觉效果或处理骰子检查 - 所有这些操作都只需几秒钟,因为所有操作都通过基本的(大多数是定制的以适应Ebb)自定义广告标签对接和自定义代码以及常规的(设计良好的)墨迹函数来完成。

"Beyond that, I also focus a lot on my own unverified theories..." #Snurre
He slaps his knees and grins. #Snurre
"<b>The Folk Spirit</b>. Have you heard of it?" #Snurre
It's something he made up. Doesn't mean it's not correct though. #int #DC18
Sounds like a collective folk view on morality. #wis #DC13

	+"No. I have not."
		--(spiritNo)
		"Understandable. It's not yet published." #Snurre
	+DC13 wis-"Is that some kind of unified moral or ethical code of a people or culture?"
		"No, it's-" #Snurre
		He leans back and squints. #Snurre
		"That's not actually that far off. You've got a head on you, Cleric." #Snurre
	+"Yes."
		"Oh!" #Snurre
		"Then tell me, what is it?" #Snurre
		
			++"I lied. I have no idea what you're talking about."
				->spiritNo
			
			++ROLL18 int-Figure it out.
				+++S
					Ah... #int
					Just look at this halfling. #int
					He's clearly walking in the footsteps of the study of unconscious mind melding. #int
					Your best guess would then be... #int
					
						++++"The Folk Spirit... is that based on the idea of universal folk myths?"
							His bushy eyebrows reach for the ceiling. #Snurre
							"Why, yes! Very good guess, Cleric." #Snurre
					
				+++F
					You stare at the halfling for about thirty seconds. #int
					"You're a quiet one, Cleric." #Snurre
					An idea pops into your empty, empty skull. #int
					
						++++"The Folk Spirit is a communal ghost that haunts us every autumn."
						++++"The Folk Spirit is a great Fordnippian wine."
						++++"The Folk Spirit? That's a music genre."
					----
					"...Not a terrible guess, but no." #Snurre
						
						++++"Yeah, I have no idea."
							->spiritNo
	
-
"The Folk Spirit is the working title for my new thesis." #Snurre
"Most of it is, if you excuse my anuran, <i>fucking bullshit</i>." #Snurre #XPGain #Minor
"But in short, it is about how each folk share a number of core communal archetypes, or myths. I have traveled around the Coast to collect as many tales, writing down thousands of stories previously only passed down orally." #Snurre
"All to see how well my theory holds up, in the minds of so, so many folk." #Snurre
He clears his throat and leans back into his chair. #Snurre
"Apologies. I am ranting here, let us put a stop to it. What do <i>you</i> want, Cleric?" #Snurre
->hub

计划可变性:动态内容和开放式设计

但是,我们限制列表中的项目编号 2(“>50% 的内容是动态的”)呢?动态内容和开放式(或非线性)设计都源于一个相似的目标:根据玩家输入创建可变性。

只要让他们做他们想做的事!尽情发挥!有一个开放的世界,你可以往任何方向走!嗯,这是做这件事的一种方法。但这里重要的区别在于,互动写作始终以作者意图为驱动的设计。换句话说,一切都由作者控制。

您仍然可以进行系统化设计,并且两者有很大的重叠,但是 互动写作的实际艺术 具体来说,就是当您 不放任 涌现出来的故事情节发展。

我的意思是:你必须要有变量。并且你必须跟踪它们。玩家做出的每一个选择,无论是角色创建时选择的属性,还是他们对哥布林首领的仇恨程度——所有这些都需要某种反馈,以引发代理现象。无论是游戏结束时的动态台词,还是整个分支剧情,这些反馈时刻与选择本身一样重要,甚至更重要。

Christoffer Bodegård的《神秘潮汐》截图 | Made with Unity。
《神秘潮汐》| Christoffer Bodegård

跟踪变量

我跟踪变量的方法简单且灵活:我称之为故事变量(SV)系统。使用标签系统,每当这些标签以标点符号开头时,就会指示变量的使用。如果该变量以前从未被遇到过,则在一个巨大的列表中创建 SV。否则,它只是访问已经存在的 SV,并根据命令设置或检查它。


++DC20 wis-\(Look for the source of the breeze.\)
	Your eyes glance upwards. #wis
	The wall. The wall is not a wall. #wis #.TE_SecretDoorRevealed=1 #UpdateEntities
	Look at the wall. #wis
		+++E-Oh?
			->END

字符串和整数 - 通常用作布尔值,但在需要时会根据需要扩展以增加或减少。我为 Ebb 实现的命令是“==”、“=”、“>=”、“<=”、“+=”和“-=”。

问题变成了组织问题。随着我不断尝试,我变得越来越擅长,但每个 SV 都使用基于位置或任务的前缀。这里的“TE”指的是茶馆区域。带有“Q”前缀的 SV 指的是任务,而“QP”指的是任务点——就像任务树中的日志条目,你的任务日志。

Yes. #wis
A symbol. #wis #XPGain #Minor
A symbol of a sun. Definitely. #OBJ
If this is what Akzel wanted you to find, you've found it. #wis #.QP3_Mine=1 #.Q_Mine=2

	+Huh. So what do I do now?
-
Get back to your dwarf buddy, of course! #dex

叙事设计收益

这是一个粗糙的系统,但有一个主要的生产力收益:您只需继续编写。需要一个动态对话选项的新变量吗?只需添加它,然后将其复制粘贴到需要设置的文件中。通过项目范围内的CTRL+F轻松检查任何变量的使用情况,或者通过基本的文本管理来管理彻底的更改。无需管理数据库。列表本身只是按时间顺序排列的。忘记某个变量的名称了吗?只需搜索相关区域或任务前缀,然后查看列表。

起初,我没有想到会这样。平均的游戏时长可能在游戏结束时会有超过 3,000 个故事变量。但是 - 和我在 Esoteric Ebb 上做的大多数事情一样 - Unity 只是与之配合。而且 ink 的 Unity 集成从未让我失望,哪怕我已经用了近十年了。重新编译 ink 文件只需要几秒钟。自定义功能以 神秘潮汐的喜好一直都非常高效。而且,尽管听起来可能很奇怪,但多年后,我仍然对这一切感到惊讶 只是流淌.如果我有能力,我希望在未来几年继续开发这个流水线。

除此之外,我还在所有写作中使用Notepad++ 神秘潮汐.虽然您显然可以使用任何您喜欢的文本编辑器,但保持轻量级和快速响应可以带来更流畅的体验。在一瞬间搜索一百万个单词,这正是让我能够编写(并修复错误!)这样一款庞大游戏的原因。

The croco-beast rushes forward and grabs you by the neck. #Kraaid #HPLoss #1d4
		
	++\(Struggle to breathe.\) "I'm actually..."
		He tightens the grip as you mutter out a faint response. #Kraaid
			+++"...a rogue." #.ROGUE+=1
			+++"...a wizard." #.WIZARD+=1
			+++"...no, no okay, I'm a cleric. I'm <b>The Cleric</b>, even." #.CLERIC+=1
			+++.BARD==1-"...I think I'm a Bard? You know what that is?" #.BARD_Choice+=1
			+++.DRUID==1-"...a Druid. I guess?" #.DRUID_Choice+=1
			+++DC17 con-"...<i>I'm Agrarian</i>...! No wait, shit. That's politics. I mean, uh..." #.AGRARIAN+=1
			+++"...I'm whatever you want me to be. <i>Please don't kill me</i>."
				"Whatever <wiggle>Kraaid</wiggle> wants?" #Kraaid
					++++"Yes...! I'll even be apolitical!" #.APOLITICAL+=1
					++++"Yes! I'm... I'm a rabbit!"
	
	++"No! I am! I'm Cleric! That's me!"

最后的想法:修复错误并学习接受分支

但这也是这个系统最大的缺点:修复错误。我本应该把更多时间投入到技术解决方案中,以修复逻辑和语法错误,但实际上,我最终通过游戏测试游戏测试来强行解决所有问题。

随着 神秘潮汐 获得 1.1 版更新,我在不到四天的工作时间里(而且工作环境非常轻松)就修复了大约 704 个“文本错误”——无论是拼写错误还是与代码相关的错误。这再次是因为这个系统非常灵活。即使这样,我们在发布时仍然存在这些错误 神秘潮汐 这也是因为这里的设置。文本量非常大,分支数量也很多。但我确信,如果没有墨水,我写不出四分之一的最终字数。

Christoffer Bodegård的《神秘潮汐》截图 | Made with Unity。
《神秘潮汐》| Christoffer Bodegård

附录:更多推荐给叙事设计师的工具

墨水使交互式写作的实用艺术变得快速,因为 .我一直对可视化脚本感到困扰,但我知道许多作家有完全相反的问题。因此,我总是建议您查看其他解决方案,以找到最适合您和您的团队的解决方案,以下是一些示例: articy:draft, Arcweave,以及 Yarn Spinner.

神秘潮汐 现已在 Steam 上架。在我们的平台上探索更多 Made with Unity 游戏 Steam 策展页面,并查看 Unity 开发者提供的更多故事 Unity 博客 以及 资源中心.