消失的箭頭:一種創作(無)分支劇情的新思路


3樓貓 發佈時間:2022-07-31 09:53:00 作者:默顏 Language

引言

我們時常在以劇情為賣點的遊戲的宣傳中看到這樣一句話:你的每個選擇都會帶來後果。可惜,在見到太多並未守住這個承諾的遊戲後,這句話漸漸開始像“狼來了”一樣,讓人視若無睹。
有時並非開發者不想這樣設計,只是分支劇情這個功能,一不留神就會以幾何級放大劇本上的工作量;還一種觀點認為,現在的玩家大多數甚至都不能通關遊戲的第一週目,開發者即使完成了紛繁複雜的劇情樹,也鮮有人能體驗到,那還不如走個形式,把一本道稍微偽裝一下就完事。
那麼是否存在一種可能,既壓縮編劇方面的成本,又能讓玩家作出的選擇切實地產生能被感知到的後果?在研究了一些敘事遊戲的開發方式後,我發現了不少共通的設計與技巧,或許能解答這個謎題。

Storylet

首先需要引入一個叫做 storylet 的概念。let 作為後綴指“小”,如果要翻譯成中文,可以是“故事片段”、“故事塊”之類,顧名思義,它指的就是分成塊的一個個小劇情片段。不過,這個詞即使在英文環境下,也不存在官方的定義,它甚至不在詞典裡——遊戲開發者們可能早已在開發時使用過這樣的概念,即便沒有聽說過這個詞。在這裡引入它,只是因為方便上下文的指代,並且近幾年來人們越來越多地使用這個詞來描述這樣形式的故事片段,所以它還可以作為一個有效的搜索關鍵詞。
使用 storylet 編寫劇本,有著與傳統意義上的“分支劇情”完全不同的思路——這裡沒有分支(所以本文有了這個令人困惑的標題)。取而代之的,每一個 storylet 都有(至少)三個屬性:觸發條件、事件內容、結果。
那麼,一個三選一、各自觸發不同劇情的分支結構:
三選一的傳統分支結構

三選一的傳統分支結構

若用 storylet 等效表達,則是:
等效表達三選一的四個 storylet,注意消失的箭頭

等效表達三選一的四個 storylet,注意消失的箭頭

事實上,不管是多複雜的分支結構,都能用 storylet 替代(互動小說作家 Emily Short 在這篇博客中給出了更廣泛的例子)。各種分支結構裡連接各個節點的箭頭們,全都消失了。當系統需要“往前推進”故事發展的時候,它不再跟著箭頭尋找下一個事件,而是去遍歷所有的 storylet,符合觸發條件的,就是下一個要進入的 storylet;而事件完畢後,用“結果”中包含的指令來更新狀態,緊接著繼續尋找下一個事件。當不止一個事件同時符合時,可以選擇條件最苛刻的那個,也可以為每個事件設置權重。
這樣的過程就是一臺不斷運轉的狀態機,在抽象的同時,也為劇本編寫帶來新的思路。

E N I G M A

讓我們用(我用首字母臨時拼湊出來的)ENIGMA 框架(Evolving,N
uanced,Interlocked,Generalized,Modular,Adaptive)來講述六個要點。

Modular / 模塊化的

由於事件與事件之間不再由箭頭帶來“強關聯性”,我們可以隨心所欲地把任何一個突然進入腦海的故事片段記錄為一個 storylet——先填上想到的事件內容,至於觸發條件和結果,則可以慢慢想。
對於某一個事件的觸發條件,大可以有多種不同的“因”一起促成。設想一個事件——獲得進入古代遺蹟的機會,觸發條件有:
  • 位於古代遺蹟門口
  • 門口的石板正在被太陽光照射
  • 主角的智力 > 10,能讀懂石板上的指示
  • (若智力不夠)主角身邊有具備“博學”特性的隊友
寫完這樣一個事件後,無需過早地操心主角是否有機會路過那片地方、天氣變化是否足夠 / 不夠頻繁、主角是否有機會把智力加到 10、有多少個隊友有“博學”特性、主角有多大概率帶著那樣的隊友……只要我們保證會在其它 storylet 中或多或少地改變這些狀態,那麼當 storylet 池足夠豐富時,這些觸發條件遲早能被同時滿足。
模塊化的另一個好處是,不管劇本寫到了什麼程度,往裡添加新的 storylet 都是非常方便的,因為它通常不會破壞任何已有的 storylet,也沒有密密麻麻的箭頭需要整理,帶來的只是某些狀態下更多的劇情走向。正如 Inkle 的創始人之一 Jon Ingold 常說的,他必須“剋制住自己在遊戲發售前一晚往故事裡添加新片段的慾望”,因為對他們的敘事引擎(ink,具體可參考這篇訪談)來說,那麼做實在是太方便了。

Generalized / 兼容幷包的

Storylet 的觸發條件可以寬容、可以苛刻,事件規模可大可小,造成的結果亦可重可輕。有“最好、最可取”的那一檔嗎?
答案是:沒有,全都要。
箭頭固然已經消失,但故事的發展仍然需要一定的脈絡。易觸發的 storylet 適合存放不該被錯過的主線事件,而反過來,像剛才例舉的古代遺蹟那種“看起來有點苛刻,也不知道多少人能撞上”的觸發條件,用在錦上添花的支線或是隱藏成就上,就再合適不過了。
量變產生質變,當大大小小的 stoeylet 足夠多以後,每個玩家經歷的都將是不同的故事。那要如何保證每一個都連貫而又精彩?接下來的幾個要點會著重探討。

Interlocked / 連鎖的

我們明明已經消除了各個事件之間的連接,怎麼又要求它們互相連鎖?其實,這裡的連鎖指的是“結果”與“觸發條件”之間要有呼應、有化學反應。小範圍內的強關聯被切斷了,大範圍內的弱關聯還是要有。
我們不想設計出完全脫離於大部隊的 storylet,不然它就真的永遠不會被觸發了。時常回顧一遍當下所有被跟蹤著的狀態,思考是否能放進林林總總的觸發條件中去。呼應越多,storylet 們就越亂中有序,邏輯上的連貫性就越好,故事也就越自然。
而對於必須發生的事,也可以採取“飽和式”觸發——為了保證事件 Z 的發生,擁有不同且互補觸發條件的事件 A、B、C,都將達成事件 Z 的觸發條件,而一旦玩家完成了 A、B、C 中的任何一個,其餘兩個就被禁用,在這一週目中不會再被遇到。這樣一來,由於玩家同時錯過 A、B、C 的概率為零,事件 Z 的發生也就是必然的了,並且 Z 發生的原因也並不單調,可謂一石二鳥。一個類似的機制:獨立遊戲 A Short Hike 中,開局需要找到的那把玩具鏟子其實很富餘,分佈在地圖的各個角落,找到一把,其他的就會悄悄消失,這麼做保證了不管玩家喜歡去哪兒逛,都能幾乎無阻力地交差,推進劇情。

Nuanced / 細緻入微的

一言以蔽之:什麼狀態都記。
是的,不管用得上用不上,即使是很微妙的狀態,都先跟蹤了再說。因為你永遠不知道,在靈光乍現時會想把怎樣的狀態放進觸發條件裡去,而一旦放進去了,我們方才所尋求的化學反應就有了。回到古代遺蹟的例子,假設我們在設計和隊友的日常對話時突發奇想:何不把討論這種古代文字也作為一個話題,可以在與博學隊友的日常對話中被聊起?那麼此時就可以加一個狀態,叫做“和隊友討論過古代文字”。當智力 < 10,身邊又沒有博學隊友時,如果“和隊友討論過古代文字”為“真”,就可以讀懂石板上的文字。這合情合理,說不定還能給玩家驚喜。
如果我們積極地在 storylet 的結果中預先標記各種稀奇古怪的狀態,那麼在設計後續的觸發條件時,就很容易頭腦風暴出各種為那麼做了的玩家量身定製的事件來。
《極樂迪斯科》的編劇 Justin Keenan 把敘事類遊戲中的此類反饋叫做 Micro-reactivity(演講鏈接:'Disco Elysium': Meaningless Choices and Impractical Advice)。他提出,對於犄角旮旯處難以觸發的劇情或文字片段,就算每一個片段只有百分之一的玩家能見到、就算投入在每一個這樣片段上的精力(編劇需要寫,接著動畫、配音等等全都需要跟上)性價比都極低,只要數量上去了,就會有相當的概率被玩家發現,成為他們回憶中的高光時刻,讓他們與遊戲中主人公建立牢不可破的精神鏈接,甚至讓他們有興趣開啟二週目,尋找更多彩蛋。
Justin Keenan 在演講中介紹橙色的那條“正常玩家”幾乎不可能觸發的“迂迴”劇情線

Justin Keenan 在演講中介紹橙色的那條“正常玩家”幾乎不可能觸發的“迂迴”劇情線

Adaptive / 自適應的

其實這一點原本用詞是 Parameterized / 參數化的,只是那樣的話就組不成 ENIGMA 這個詞了。不過仔細想想,Adaptive 或許更合適。
言歸正傳,要點在於,每條觸發條件儘量不要“寫死”。
小明是一個有“博學”特性的隊友,小紅也是。那麼進入古代遺蹟的那個條件,為什麼要寫成主角身邊有具備博學特性的隊友,而不是主角身邊帶著小明或小紅呢?因為日後我們可能會設計更多的隊友可供選擇,寫得寬泛一點,就為這些潛在的改變做好了“自適應”的準備。
同樣道理,因為我剛才用的是“門口的石板正在被太陽光照射”,而不是“太陽光直射了石板”,我為“主角智力爆棚,用鏡子把本來照不到這裡的太陽光折射了過來”這個可能性留了一個後門。這樣的寬限越多,遊玩時的可操作空間就越大,對那些喜歡不走尋常路、尋找奇妙過關方式的玩家就越友好(雖然這一點聽起來更像是沉浸模擬類遊戲 gameplay 上的特色,但我認為放在劇情驅動的遊戲中也很酷)。
自適應的另一層意思是,storylet 事件中的具體內容,完全可以參數化、與觸發條件同步。在觸發之前,隊友名可以用 XX 替代,一旦觸發,所有的 XX 都將被替換成“小明” / “小紅”,總之就是那個擁有“博學”特性的隊友名。《漫野奇譚》開發者在一次講座(Youtube視頻:“Nate Austin | Procgen in Wildermyth: Storytelling | EPC2021”)中介紹了他們的劇本生成系統,根據一系列前置條件和人物特性選擇當下最合適的劇本與臺詞,思路和我們這裡提到的非常像。如果你玩過並記得自己的幾個主角如何在漫畫裡一格格演繹他們的專屬故事,那麼你或許已經明白這種“自適應”性想要達到的效果了。
《漫野奇譚》中的“劇本生成器”一瞥

《漫野奇譚》中的“劇本生成器”一瞥

Evolving / 自我進化的

這一點硬要算的話可以歸入上一點中去,只是那樣的話就組不成——啊,還是言歸正傳吧。
Storylet 內的具體內容是可以根據各種狀態而自我調整的,不僅僅取決於觸發條件中要求的狀態,更應該取決於遊戲世界中任意的狀態,只要合情合理。
例如,主角說話提及某人時,如果已經認識該人,就可以用姓名來指代;否則,就可以說“那個帶著帽子的高個兒”、“那個煙不離手的人”等,從實時的狀態中挖掘出特點作為指代詞。再比如,若主角曾經在沙漠 / 森林 / 遺蹟中短暫地拋棄過隊友小明,那麼日後主角和小明發生口角時,小明就可以說“當時你在 XX 做的事,不要以為我忘記了”,根據記錄過的狀態,用沙漠 / 森林 / 遺蹟來填入 XX。
一個現成的例子,是《陷陣之志》中由克里斯·阿瓦隆(Chris Avellone)負責的 bark 設計。
在這裡插一段題外話:如果你對 bark 的概念感到陌生,不妨讀一讀我更早的一篇日誌:合理巧妙地設計遊戲中的 Bark 以幫助遊戲敘事。雖然這裡我們討論的是 storylet 而非 bark,但是這兩個概念、甚至包括各自的例子,都有著相當多的共通之處。這也是為什麼如果你去看《黑帝斯》的對話設計(Youtube視頻“The System Behind Hades' Astounding Dialogue”),《看火人》的對話設計(Youtube視頻“Interactive Story Without Challenge Mechanics: The Design of Firewatch”),會發現提到的技巧皆與本文談及的高度重合。從某種角度上看,將 bark 高度抽象化以後,就成為了 storylet。
回到《陷陣之志》,細心的玩家會發現,當我們戰場上發生關鍵事件——如擊殺蟲子、切斷蛛絲、time pod墜落——後,機師或是建築物內的居民們會說一句話,巧妙就巧妙在這句“即興”的發言每次都很應景,而箇中原因,可以在這篇訪談中找到。簡單概括,就是為每一句 bark 都設置細緻入微的觸發條件,並且活用佔位符來指代各種變量
從訪談中的一個例子來看佔位符的作用:
It’s the difference between: “Good shot, pilot 3!” vs. “Good shot, Jones. Doing Archive proud!” (Which would be written as “Good shot,
#self_last. Doing #corp proud!”)
“打得漂亮,3號機師!” 對比 “打得漂亮,瓊斯!你可真是為 Archive 公司增光了”,哪句能給人更強的臨場感,顯而易見。
總之,storylet 中等待著被激活的故事片段,可以包含許多需要被填充、被前文慢慢滲透的部分。隨著既定事實越來越多、被跟蹤的狀態越來越豐富,這段故事最終被激活時,就已經“進化”完畢、有血有肉、能夠多點開花地呼應前文了。

更多的是自由

講完 ENIGMA 框架,你可能注意到,雖然我們規定了一些 storylet 之間的呼應方式,並建議要把每個 storylet 裡的事件做得靈活可塑,但自始至終都沒有談到這些所謂的“事件”到底要有怎樣的結構、以怎樣的方式存在。
其實這是有意被略去的一塊,因為事件不需要有固定的結構。一個 storylet 中的事件,是完全自由的:它可以是三五行就完事的劇情片段,也可以是一幕,也可以以你一句我一句的對話體存在,甚至可以套一堆更小的 storylet 進去,還可以把傳統的分支劇情放進來——實際上這可能是非常強大的一種組合。只要宏觀上存在觸發條件和結果,不影響大狀態機的運作,那麼這些處理方式全都可行!至於孰優孰劣,就完全取決於開發時對敘事的要求了。
所以從某種角度來講,ENIGMA 這個詞挺合適的——海量的 storylet 不遠不近地共存著,近看很謎,遠看很亂,但當大狀態機的齒輪真正轉動起來的時候,奇妙的秩序終於浮現。
不過,這一套創作方式,也存在著幾個大的缺點 / 侷限性:
  • 過於龐大的排列組合使得測試變得非常困難。Storylet 數量上去之後,就很難再人工遍歷所有可能的故事走向了。
  • 本地化變得很棘手。在一種語言中寫好了的、等待填充與“進化”的語料,可能並不是直接翻譯就能放到另一種語言中去的。
  • 之前 Justin Keenan 指出的問題非常實際:成本不好控制。作家是可以天馬行空地自由發揮了,今天靈感來了,加十個 storylet 都不覺得夠;明天重新審視,刪掉五個;後天繼續隨心所欲地創作,反正怎麼寫都搞不壞這個系統……這套框架非常適合劇本本身的高效產出,但配套的後續工作就很容易被打亂。考慮到這點,或許還是以文字為主要表現形式的遊戲最能在這裡吃到甜頭。

選擇的後果與可能性空間

Storylet 的思路配合 ENIGMA 框架,處處都留有讓遊戲劇本更有機、更能響應玩家選擇的機會。而這裡附帶一些更加普適的建議,以補充回答如何讓遊戲顯得更加“響應式”、如何讓玩家發覺故事存在著另外的可能性:
  • 在事件觸發時是否要將觸發條件也告訴玩家,是值得思考的一個問題。聯想遊戲中的對話菜單,各家也都有不同的做派。
  • 《神界:原罪2》中因為角色特性而解鎖的對話選項,會在左邊的中括號內有專門的提示,這樣起碼玩家知道了這些特性正在以怎樣的方式改變這段對話。
  • 《極樂迪斯科》中則有意隱藏了這樣的提示,為了讓玩家感覺更貼近現實生活中的對話。
  • 《看火人》看似簡單幹練的對話系統,背後有著複雜的機制來選取當下最有趣的話題,而開發者同樣沒有把任何凌駕於主人公所知之外的信息展示在 UI 上。結果就是,在遊玩時我的確體驗到了連貫通順、代入感強的五小時“步行模擬”,但直到後來看開發者的講座才知道,原來我的 Henry 與 Delilah 所聊過的,只是遊戲準備了的內容的冰山一角。
  • 說到這裡,又得提一提《史丹利的寓言》了。作為可能是最“響應式”的敘事遊戲之一,試想,如果它從頭到尾都有一塊 UI 告訴你後臺正在記錄哪些狀態,那麼當評論員看似精準地評價你的行為的時候,你還會感到驚喜嗎?(當真那麼做的話,倒也不失為對電子遊戲中所謂“玩家自主權”的一種奇妙解構——反正這多少也是《史丹利的寓言》本身已經在探討的問題了)
《看火人》主創之一 Chris Remo 指出針對響應機制的處理方式的兩種方向——隱藏以獲取沉浸感、用 UI 時刻提示玩家

《看火人》主創之一 Chris Remo 指出針對響應機制的處理方式的兩種方向——隱藏以獲取沉浸感、用 UI 時刻提示玩家

  • 在事件完成後是否要將結果告訴玩家,亦有利有弊。《永恆之柱2》中,做出影響聲望的對話選擇後,UI 會直接告訴我們這一點。《奇異人生》中的關鍵分支選完後,屏幕角落會出現蝴蝶振翅的簡短圖標,暗示這個選擇的分量。這的確能讓玩家心裡“咯噔”一下,期待後續的發展,但是最好不要在這裡玩“狼來了”的騙局。
  • 在事件完成後,可以不借助 UI,間接展示其它的可能性,以保護沉浸感。例如:讓主人公自言自語“我剛才本可以 XXX 的”。
  • 在關底或遊戲結束時給出路線分支圖,或是有關選擇的統計數據。看到有 X% 的玩家也選擇了 XXX,不僅能知道自己有多趨同/異類,也能一瞥其餘的可能性。
  • 記錄一些連續發生的事件,給予特殊的回應。例如:在那些可以接收打字作為命令的復古文字冒險遊戲中,若系統連續 5 次都沒能在玩家打下的那句話中找到有效的動詞,那麼除了告知“無法識別您的指令”外,還可以加上幾個有效動詞的例子,臨時性地輔導玩家推進劇情。同理,《俠盜獵車手 5》中,任務失敗若干次後,系統會詢問是否需要跳過該段劇情。這個思路也不必總是用在異常狀態上,事實上,把它用在司空見慣的小事上效果更好。如果一個商人 NPC 察覺到玩家連續 N 次造訪時都沒有戴頭盔,他大可以說一句“你就這麼放心你的腦袋?”,甚至可以臨時決定為店裡的頭盔降價促銷。
  • 觀察事件發生的時間間隔,給予特殊的回應。《黑帝斯》中,如果這一局結束得特別快,會在復活後遭到特殊的嘲諷,想必是因為遊戲計算了你從出生到陣亡的間隔。

結語

遊戲敘事從來不存在公式或是萬金油,但這也恰恰給了開發者們用來突破的一個口子。時不時地,我們就能看到一些小成本 / 獨立遊戲靠著好看或是好玩的故事,從層見迭出的 3A 大作那兒奪去玩家們的目光。
僅僅因為“我想講一個故事給你們聽”而決定做遊戲,或許也是一件浪漫的事。而我一直相信,互動敘事還存在著很大的開拓空間去成全這份浪漫,讓作者能講得更精彩,聽者能聽得更入神。希望本文像 ENIGMA 框架一樣,亂中有序,為你們帶去了啟發。

擴展閱讀

RESPONSIVENESS IN NARRATIVE SYSTEMS (論文的篇幅相當大,但帶來的也是對敘事遊戲中“響應度”的鉅細無遺的剖析)
《80 days》:如何以軟件工程的思路編寫一部互動小說(由低多邊形厭氧菌於 2019 年發佈的文章,本文所說的 storylet 其實本質上和該文章介紹的“故事模塊”是同一個思路,只是那篇文章更側重對遊戲 80 days 本身及其敘事方式的討論。總之,如果你覺得閱讀本文有了收穫,那麼強烈建議也讀一讀那篇)
遊戲分支劇情創作中的挑戰和工具(側重技術實現層面的、對分支劇情創作工具的介紹。出現的幾個工具中,ink 尤其適合運用本文中提到的思路)

© 2022 3樓貓 下載APP 站點地圖 廣告合作:asmrly666@gmail.com