好,想象一下:你做出了史上最受喜爱的独立游戏之一——《时空幻境》(Braid)。
它带来了数百万美元的收入。这简直就是独立游戏开发者的终极梦想,太酷了。于是你继续做下一款游戏。你想做一款规模庞大的解谜游戏,于是做出了《见证者》(The Witness),它同样创造了数百万美元的营收。然后你开始做第三款解谜游戏。当然,你想让它比前作稍微大一点,但仍然想保持简单。没错,你当然还想自己做一套定制引擎。然后嘛——干脆再创造一门自己的编程语言好了,为什么不呢?
接下来,日复一日,年复一年,这个项目不断膨胀,越来越大、越来越大。突然间,时间来到 2025 年。某天早上醒来时,你意识到:自己已经在同一款解谜游戏上干了整整十年。这就是本期嘉宾乔纳森·布洛的故事。他最近在游戏大奖颁奖典礼上公布了这个历时十年的项目,名叫《沉星之序》(Order of the Sinking Star)。每当我看着这款游戏,脑海里总会浮现几个词:美丽、精巧、复杂、深邃、庞大——也许还有一点疯狂。
不过别只听我说。接下来,让我们和乔纳森·布洛聊聊这段十年旅程,也聊聊自从他在 2014 年推出上一款商业游戏以来,游戏开发世界发生了多么巨大的变化。我们会谈到 2026 年该如何营销独立游戏;在游戏行业动荡不安的时期,该如何为自己的游戏定价;对于独立开发者来说,哪个平台更合适——Steam 还是主机;以及为什么发行商在 2026 年依然重要。没错,他们确实还有价值,而且乔纳森·布洛这一次真的选择了与发行商合作。
我们还会聊到《沉星之序》中那些华美的画面是如何制作出来的,以及它们为什么如此昂贵;乔纳森为什么要创造一门定制编程语言和一套定制引擎。最后,在播客结尾,我们会直接进入他的自研引擎,由他亲自展示《沉星之序》究竟是怎样制作的。非常迷人。呃,这场对话真的……有点疯狂。
你觉得,如今营销《沉星之序》,和当年营销《见证者》或《时空幻境》相比,是不是已经完全换了一套玩法?
完全不一样。现在的互联网和以前真的很不同。《见证者》是十年前推出的,而放在互联网的时间尺度里,十年实在太漫长了。
在互联网世界里,十年简直像无限久,对吧?首先,现在的游戏多得多了。人们的注意力也有更多去处。社交媒体当年当然已经存在,现在也存在,但如今它已经膨胀到占据人们更多注意力的程度。因此,游戏现在还得和那些根本不是游戏的东西竞争。
这让事情变得更困难。我好像看到过一项统计,说人们在游戏上的总支出实际有所下降。也许是 2024 年,或者最近某一年,总体支出确实下降了。另外,游戏价格似乎也在下降——我不知道你有没有看到那篇文章。
可他们也尝试过涨价,对吧?他们试过卖 80 美元、100 美元。这个事情很奇怪,因为我小时候玩个人电脑游戏时,好像一款游戏就要 40 美元左右。
按通胀折算到今天,那就超过 100 美元了,对吧?可能相当于 120 美元左右。
所以从这个角度看,100 美元的游戏似乎也说得通。但如今游戏普遍得多,也更容易制作。虽然大量游戏依旧很糟糕,但游戏整体确实比过去更好了。可正如刚才所说,现在人们可以花费时间和注意力的事物也多得多。
所以游戏得和所有这些东西竞争。昨晚我听一档播客,他们在讨论 80 美元的游戏。我当时就在想:没错,即使对我来说——我在游戏行业已经待了很久,一般额度的消费也不会让我太纠结——但 80 美元买一款电子游戏,听起来还是很贵。
所以我也不知道行业最终会怎样应对。如果大家只是一味打价格战、竞相压低售价,我不会意外。也许这种事已经在发生了。可如果整个行业都走向那条路,也就会变得像 iOS 市场一样。我可没听说过哪个认真玩游戏的人会说,iOS 是自己玩复杂、高品质游戏的首选平台。这样下去,我们或许是在把自己往悬崖下面开。
因为你想啊,如果把价格压得特别低,就会发生两件事。
第一,利润空间会变得非常薄,也就是说,一款游戏预期能赚到的钱只比成本多一点点。这样一来,行业就会倾向于采用工业化生产方式。农业的利润率就很低,种地其实赚不了多少钱,于是才会出现那些依靠规模经济盈利的超大型工厂化农场。iOS 上发生的事情也有点类似——某种意义上,那些是“流水线游戏”。
所以,如果你希望看到富有创造力的独立游戏,这种趋势大概不会有帮助。当然,也可以换个角度说:以后还愿意独立做游戏的人,也许只会是那些真正、真正热爱这件事的人。
这或许也是真的。但我不知道,这很难。我觉得,如果有人认真做出了一件相当不错的作品,投入了大量劳动,那么只要我欣赏他的努力、也想玩他的游戏,我就应该愿意付给他一个体面的价格。
可这个“体面的价格”是 100 美元吗?我不知道,我不觉得非得卖到 100 美元,对吧?
假设《沉星之序》有 800 小时的游戏内容。也许真有这么多。
好吧,那就 500 小时。也许 500 小时。先说明,这可不是承诺。
对,它就是一款非常庞大的游戏。不过我们姑且假设它有 500 小时内容。谁会真的玩满 500 小时呢?你不能按照“最多可以玩多少小时”来衡量价值,对吧?或许可以按最低时长,或者某个偏低的时长去估算。比如游戏只有一小时,那你确实可以做个简单估值,说它是一款 5 美元的游戏。我之所以这么说,是因为这件事真的很难判断。我自己最近也一直在为定价纠结。
因为我的《扭曲之塔》(Twisted Tower)明年就要做完了,应该是明年年初。
是,是。可我做试玩测试时,所有测试者都说:“30 美元,或者 25 美元——就该卖这个价。”但我知道,《沉星之序》应该是有发行商的,对吧?
可我刚刚和自己的发行商聊过,我们都在想:现在这个价格恐怕未必行得通了。它可能只能卖 15 美元。
这得看情况。我也不知道。我们还没进行过类似的定价讨论。
毕竟我们刚刚宣布游戏会在明年推出。但老实说,我也不确定。当年《见证者》发售时,我们定价 40 美元。对于当时的一款独立游戏来说,这个价格夸张到足以成为新闻、引发争议。大家会说:“天啊,你们怎么敢?”因为当时也有游戏卖 30 美元。可能也有少数游戏卖 40 美元,但非常罕见。可我的想法是:听着,我不知道究竟会有多少人买这款游戏。
就算有人愿意买,我估计也只会有一小群真正喜欢解谜游戏的核心玩家,非常渴望这样的作品。
那么,我们也许必须从这群核心玩家身上获得足够收入,才能维持生存,对吧?所以我把价格定得稍高了一点。当然,我当时的判断是:这是一款规模很大、设计非常复杂的游戏,我觉得它绝对值 40 美元。但每个人都会自行判断 40 美元对自己意味着什么,以及什么东西值得自己花这笔钱。
不过现在回头看,这件事其实没造成多大问题。人们真正玩过之后,会觉得:“哦,这真的是一款完整、正式的游戏,不是什么小打小闹的独立作品。”
在那之后的这些年里,我们已经见过不少独立游戏。我本来想说,这类游戏所占的比例越来越高——不,不能说比例,因为现在每天都会冒出太多粗制滥造的东西。但你确实可以举出许多例子:一些独立游戏规模庞大、内容扎实,能把玩家想从中得到的东西全部给到。如今我们已经习惯了这种情况,而在当年,这类先例还很少。那时人们对独立游戏的印象更像是:“它还不算真正的游戏,不过已经很接近了。”
这些年来,我们只是在这方面逐渐做得越来越好。你刚才用了“复杂”这个词,我也会说你的游戏非常复杂。事实上,我觉得它们对我来说可能有点过于复杂了。
我总是看我兄弟玩你的游戏,自己却从没真正玩过。我就坐在旁边看,因为我是搞美术的。我很想聊聊《沉星之序》的美术,因为它实在太棒了,细节特别丰富。
总之,我是做美术的,所以你的游戏对我而言非常复杂。我在想,会不会正是这种复杂度,让《见证者》这样的游戏能够卖得更贵。原因在于——这话听起来很糟——你其实并不希望什么人都随便进来玩你的游戏,对吧?因为很多人会玩得很挫败。
你想要的是那种会说:“不,我一定要坚持把它弄明白”的玩家。你的游戏是不是必须得“硬啃”过去?那是一种很特殊的磨炼,对吧?
这得看情况。要看你有多喜欢解谜。尤其在新游戏里,我们正努力让它少一些“硬啃”的感觉。这确实是我一直有意识在关注的问题。
哦,在继续深入之前,我先把《见证者》的定价故事讲完。
现在回头看,如果当初把价格定在 30 美元而不是 40 美元,我也许反而能赚得更多。因为尽管出于刚才那些原因,确实有相当一部分人愿意花 40 美元买它,但这个价格仍然高于当时的普遍价位。我觉得很多人面对一款不了解的游戏时,会想:“哦,我听说过这款游戏。”
“也许我想玩,也许不想。”对吧?他正处在犹豫的边缘。
这时候,他很可能就会开始认真考虑它究竟卖多少钱,对吧?
因为对他来说,这完全是一个未知产品。后来事实证明,这款游戏的受众比我预想的更大众。当然,它不像任天堂游戏那样真正面向大众,但对于一款古怪的独立艺术解谜游戏而言,它的吸引力远比我想象的广。因此,如果当时定价更低,我们也许会表现得更好。我不知道。但做这种决定时,你手里的信息永远不完整、不完美,只能根据当时知道的一切,尽力做出最好的判断。
那你的大部分收入——你不必回答这个问题——是不是一直主要来自主机平台?
无论《时空幻境》还是《见证者》,情况都差不多。不过这话要打个很大的折扣,因为我已经很久没看过它们最初的销售数据了。就拿时间更近的《见证者》来说,首发时 PC 和主机大致各占一半。但随着游戏变老,比如过了几年,它已经成了一款老游戏,我认为 Steam 更擅长让老游戏继续保持生命力。主机平台上,会有好几种因素叠加在一起。
也许我甚至在所谓的“主机战争”里换了阵营。因为不同主机的发售节奏有时并不同步。比如我以前是 Xbox 玩家,但索尼先推出了新主机,于是我就升级到了索尼那边。这样一来,那款老游戏如果还只在旧主机上,我就不会再买了,因为那台旧主机平时都不怎么接上电视。
这是一个原因。另一个原因是,我觉得主机商店本身的性质决定了老游戏更难被发现,主要和它们的界面设计、操作方式之类有关。
我觉得就是这个原因。浏览起来不够快、不够顺手。你在 Steam 上可以随便点来点去,一口气把十款游戏加进愿望单。
当然,我要说 Valve 在这方面做了很多工作。我不是在说他们什么都没做。我只是在想,如果 PC 上不知为何也只能使用手柄,那么 Steam 为搜索和发现游戏而设计的那些功能,可能会和现在完全不同,对吧?仅此而已。总之,我想表达的是:一款游戏进入长尾期后,我们看到的收入会明显更偏向 PC;但在首发阶段,两边通常比较均衡。
当然,这也取决于你到底登陆了多少个平台,以及其他各种因素。
那么,我是否可以说,《沉星之序》现在的重点是 Steam?在这个游戏开发时代,Steam 会是你的优先平台吗?
当预告片在游戏大奖上首播时——大家可以去 YouTube 看,简介里会放链接——
预告片结尾,我们确实明确请大家去 Steam 把它加入愿望单。
除此之外,我们没有公布别的消息,因为目前其他平台的计划还没有完全敲定。
明白。不过你们正在推进其他版本,希望能在一些主机上同步发售?
对,和 Steam 同步。但具体安排还没有完全确定。接下来几个月里,我们也许会公布更多信息。
我想也许可以换个更好的问法。我一方面是在替观众考虑,另一方面也是在替自己想:作为一个独立开发者,我究竟应该怎么做?
这么说吧,如果你完全从基本原则出发,想弄清楚“我应该把游戏发布到哪里,才能让人玩到”,那我认为 Steam 依然是最容易进入、也最容易触达最大规模受众的平台。你当然也可以上主机,只是难度更高。现在已经不像过去那么难了,但你仍然得经过认证,以及完成其他手续。
比如你还得给游戏做年龄评级,虽然现在这件事也比以前容易了。
可能彻底消失得无影无踪,对吧?当然,在 Steam 上也可能如此。但如果你正在拼命争取让人注意到自己的游戏,Steam 上至少还有那么一点可以攀住的“岩缝”,让你有机会往上爬;在主机平台上,这会更困难。所以,如果你是一个资源有限的独立开发者,只能做好一个平台,问自己应该去哪里,我认为答案仍然是 Steam。
而且,如果你完成了 Steam 版本,那么要做 itch.io 或 Epic Games Store 版本,绝大部分工作其实也已经完成了。你自然也就有机会进入这些商店,因为核心工作基本就是让游戏在 Windows 或类似环境上正常运行。因此,对提出这个问题的人,我会这样建议。主机当然也很好,那里依然有大量玩家。但登陆主机更困难,需要投入更多精力,而且最后可能会让你失望。
对。我能问一下吗?这段你想剪掉也没关系——为什么这一次你选择了发行商?
有两个原因。第一个原因,就是我们刚才一直在谈的:现在的互联网太嘈杂了,事情很难做。
即使有人本来就对你的游戏感兴趣,也可能根本不知道它已经发售。我们推出《时空幻境:周年纪念版》后,就听到过这样的反馈:游戏发售几个月之后,还有人说:“什么?它已经出了?我完全不知道。”所以我们想避免这种情况。我也了解自己。一方面,我确实认为营销和宣传非常重要。
对我来说,它不是最重要的,因为游戏品质才是第一位的。但如果你把游戏做出来了,却没能把它送到玩家面前,那同样是个问题。
是啊,现在确实更难了。回到《时空幻境》那个年代,平台上当然也有各种守门人,他们可能会拒绝你的游戏,但整个环境还算讲道理。如果你真的做出了好东西,大概率总能以某种方式获得成功,因为市场还没那么拥挤。现在,你可以做出一款好游戏,却始终无人知晓,只能一直被搁在那里。
它比我们以往做过的任何东西都更庞大、更复杂。越接近发售日期,我们就越会像所有团队一样,为了把一切做完而疲于奔命。而我肯定没办法同时把营销做得很好,因为真正把宣传体系搭起来、组织好所有事情、弄清该联系谁、该怎样介绍游戏,都需要大量时间和精力。
我当时就想:我太了解自己了。如果让我在“做营销”和“把游戏开头的玩法做得更好”之间二选一,我一定会去改进玩法。
可这样一来,我们就可能在现代互联网的噪声里栽跟头,最后卖不出足够多的份数。所以第一个原因,就是找一个合作伙伴,专门让这套营销机器运转起来。当然,我自己仍然得参与其中。
比如做媒体采访时,我肯定会出面。但我不再需要亲自发起、安排这些事情,也不用自己研究该找谁、该怎样建立联系。
第二个原因和资金有关。我们确实获得了一部分用于完成游戏的资金。到目前为止,我们已经在这个项目里投入了巨额资金。幸运的是,《时空幻境》和《见证者》在商业上都很成功。但事实证明,如果你在一款游戏上工作九年或十年,那么就把你认为合理的年度烧钱速度——
那就会变成一个很大的数字。那我能问一下,每年多少算是合理的烧钱速度吗?
这得看情况。对我们来说,这个数字一直在变化,取决于当时在做什么、有多少全职员工。有时候临近发布,我们会在几个月内请一批外包人员做移植,这时烧钱速度就会突然大幅上升。
不,我可以给个区间,让大家有个概念。我觉得这些信息对某些人确实有用。首先,我们是一家小公司,目前大约有十名全职员工,此外还有外包人员。如果把所有以兼职、部分工时等方式参与《沉星之序》的人都算进来,大概有二十人左右。
不过团队规模一直在变,烧钱速度也随之变化。过去十年里,我们每年的支出大概在 180 万美元到 440 万美元之间。440 万美元通常是我们开足马力、拼命要把某个东西推向发布的时候。
那我们取个中间值,假设每年 300 万美元。连续九年,每年 300 万,就是 2700 万美元。
这是一大笔钱,对吧?所以你完全可以想象我会说:嘿,我的钱差不多花光了,还需要再来一点,才能把游戏做完。
老实说,我的烧钱速度完全没那么高。像《扭曲之塔》——
你应该庆幸没有那么高。《扭曲之塔》的总预算要低得多——这可能会让人意外。你看过《扭曲之塔》吧?好像有人跟我说你看过。
对,对,对。那款游戏的总成本可能不到 70 万美元,开发了大约三到四年。这很不错。
这正是问题所在。最初的《时空幻境》开发时,我住在旧金山。那里当时也不便宜,虽然还没有现在这么贵,但绝对算不上低成本。不过团队基本只有我一个人,我付钱请大卫·赫尔曼(David Hellman)帮忙做美术,埃德蒙·麦克米伦(Edmund McMillen)也为它做过一些美术。
真的。他确实做了一些,此外还有音效之类的其他零碎工作。我记得最后算下来,那款游戏的总预算大概是 22 万美元。
所以折算到今天会更多。但还是会让人感叹:哇,我以前竟然能用这种预算把东西做出来。我真怀念那些日子。
《沉星之序》的画面精度正是让我特别震撼的地方。我第一次看到它时——我也很想听你介绍这款游戏、听听你的核心卖点——最初我以为:“好,这大概是一款俯视视角的 2D 游戏,只是美术特别漂亮。”可后来我发现它是 4K 的。
画面非常漂亮。我把画面放大后才意识到:“原来这一切都是 3D 的,每一个小东西都做成了细致的 3D 模型,对吧?”
太美了。而且那些着色器,我甚至很难准确描述它们的效果。因为我用 Unity 工作,所以我就在想:这些着色器应该都是你写的吧?
不是我一个人写的。我只写了其中很少一部分,我们有一支程序团队一直在做这些着色器。
我之所以想问,是因为今年早些时候我采访过肯·莱文(Ken Levine)。
还有亚美利肯·麦基(American McGee)。
他们两个人都说,如今如果想做这种水准的美术,就很难真正把游戏做得更便宜,因为美术实在太昂贵了。
即使到了现在,美术依然很贵。所以我想问:游戏的大部分预算是不是都花在这上面了?
我会说,这是多种因素共同造成的。至少从我们现在冲刺收尾阶段的团队构成来看,美术人员比其他岗位都多。我们有五名全职员工专门负责关卡环境建模。考虑到游戏规模这么大,我当然很容易希望人数能再翻一倍。
但你总得把预算控制在相对合理的范围里。这款游戏确实非常大。你刚才说它是俯视视角——“俯视”可能有点夸张,更准确地说,是一种类似《暗黑破坏神》的视角。放在过去,人们可能会称它为等距视角。
有时你可以移动相机,但通常没有必要。大多数时候,它就是固定在那里的。
游戏中的绝大多数关卡都能容纳在一个屏幕里。而这种单屏关卡,大概有 900 个。你可以想象,为这么多关卡制作美术要花多大的工夫。此外,我们还有一个庞大的世界地图;也有些关卡并不是单屏规模,其中一部分本身就非常巨大。
那又意味着更多工作。归根结底,就是有大量实打实的制作任务必须由人完成。而在开发早期,你还在摸索游戏究竟应该是什么样子。因此,早期做出来的美术并不一定能进入最终成品。因为那时你甚至不知道游戏最终应该长什么样。项目刚启动时,我只有一些高层次的方向,而这些方向并不能直接变成屏幕上的像素。
比如其中一个高层要求是:我特别讨厌某些基于网格的游戏,角色全都瘦得像火柴人,视觉上看起来完全可以从彼此身边擦肩而过,可规则却说他们会互相阻挡。所以,我们会把角色做得比较矮壮,物体也比较敦实。还有,我讨厌玩解谜游戏时,因为美术干扰而看不清东西的确切位置;或者只有亲自走过去试,才知道某个地方能不能通行。那我们就提前把这些问题解决掉。
于是你先有一组这样的目标。当然,还有一些隐含目标也需要偶尔明确说出来,比如我们当然希望游戏看起来真的很棒,等等。
接下来,你得从这些抽象目标一路找到实际制作关卡时该怎么做。
网格模型应该长什么样?纹理要怎么做?尤其当你使用自研引擎时,好处在于:为了让画面好看,我们想写什么着色器就能写什么着色器。但这同时也是一种诅咒,因为它会变成一个吞噬大量精力的无底洞,还会带来一种“选择悖论”。
既然任何着色器都能自己编程实现,可做的事情就太多了。那我们究竟该选择做什么?仅仅做出这些决定就要花费很长时间。这款游戏表面上似乎并没有怪到哪里去——就是一些角色在基于网格的场景里移动,你一眼就知道那是什么类型。但真正了解它在做什么、怎样运作之后,就会发现它其实非常古怪,与其他任何游戏都不一样。我们用了很长时间才把这些东西想明白。
还有一点。我做游戏时,无论编程、设计还是其他工作,方法都非常务实。这和我刚进入游戏行业时的经历有关——那个年代,想把任何东西真正做出来都非常困难。当时没有现成引擎可用。我入行一两年后,你也许可以花 50 万美元授权 id Tech,但拿到的基本就是《雷神之锤》初代那套技术。
如果你做的游戏和《雷神之锤》差不多,那当然有用;可如果你要做的是别的类型,它就帮不上太多忙,对吧?
而且我也没有 50 万美元。授权费好像就是 50 万。
对。现在回头看,这个价格可能甚至显得不算高。但和今天相比,当时的 3D 游戏数量实在少得多。
加引号的“免费”。如今已经是一个完全不同的世界了。
总之,当时人人都得自己做引擎、自己摸索怎样开发游戏。大多数决定做游戏的团队,最后甚至连一个真正能玩的东西都没做出来,就彻底失败了。现在不同了。现在你打开 Unity 的测试示例项目——不管它叫什么——五分钟后就能让一个角色在场景里走动。
对,真正困难的是从那里继续走下去,做出一款有人愿意玩的游戏。
可在当年,光是让某个东西能在你的电脑上运行起来就已经很难了。
所以,我等于是被那种环境的烈火锻造出来的。现在无论做什么,我的第一步总是:尽快朝目标靠近。在这个过程中,我们会故意做一些明知还不够好的东西。比如写程序时,我可能会说:“好,这个函数是个非常愚蠢的临时补丁,但以后能换掉。”
我知道以后可以替换它。现在先让项目尽量接近目标,这样才能看到实际效果,判断是否需要调整,也能验证它是否真的能带来我们预期的体验——比如它究竟好不好玩。问题在于,开发这个项目之初,我们做了自己的游戏引擎。而之所以做自己的引擎,是因为我先创造了一门新的编程语言。我想用这门新语言编写引擎。我们为上一款游戏制作的自研引擎全部用 C++ 编写。我当时想,虽然可以移植其中一些部分,但实际上我们还是相当于从头做一套新引擎。
那门语言也是你创造的吗?它叫 Jai,对吧?是这么读吗?
它其实没有正式名称。Jai 只是代号,不过大家怎么叫都行。
我会说,它在某种意义上是 C 和 C++ 的后代,因为它是一门系统级语言,不采用托管内存。你可以获取对象的指针;只要愿意,也完全可以借此把电脑里的内存全毁掉。
但在语法上,它也稍微继承了一些函数式语言的特点。比如有一门语言叫 Standard ML of New Jersey,对它有一点影响——不是很多,但确实有一些,还有其他类似来源。
顺便说一句,你现在是在和一个外行聊天。我是做美术的,只会 C#。
几乎没人会使用我刚才提到的那个具体方言,但它属于一门叫 ML 的语言。这里的 ML 不是“机器语言”,大概是“元语言”(Meta Language)的缩写。它是函数式语言的一条分支。沿着这条谱系发展下来的现代语言,例如 OCaml。
我正想把这些关系弄清楚。那我们换个话题,来聊《沉星之序》。我想听听关于它的一切。为什么这款游戏要使用一门自定义语言?你想达到什么目标?这和游戏本身有什么关系?尽管展开讲吧。
当年我开发《见证者》时,项目会走到这样一个阶段:你感觉游戏已经快做完了,但事实上之后可能还需要再开发一年。可至少它已经完成到让你能够说:“好,我现在看得出这款游戏究竟是什么了。”
开发早期往往存在一些巨大的风险,比如:“如果某件关键事情做不好,这款游戏就会彻底糟糕。”但到了某个阶段,你会越过这些风险,然后说:“好,它还需要进一步打磨,但已经足够好了。它已经具备了成为一款好游戏所必须做到的那件事。”
当时我们已经越过了那个阶段,可剩余工作依然很多,大概还有最后一年半。
我每天去办公室,用 C++ 编程。C++ 是一门很难看的语言,编译游戏又需要很长时间。团队一夜之间会提交很多修改,而我每做一次改动都得等很久。除此之外,还有一些构建流程方面的问题,如今回头看,我希望当时能处理得更好。你知道,开发游戏时总会有各种构建流程需要运行。
比如我们总得想办法管理各种数据。美术团队做了一堆新内容,我早上来到办公室,就得先更新、从某个中央服务器把它们全部拉下来,这需要时间;接着,这些资源也许还得在本地进行某种处理,又要花时间。所有这些等待不断叠加。我已经连续辛苦工作了很多年,本来就很疲惫,每天到了办公室,却因为一切都太慢而感觉处处受阻,根本没法顺畅工作。
在我的游戏开发生涯里,这种感受并不是第一次出现。但这次有一点很不一样:这是一个完全由我负责的项目,是我亲手建立、亲自启动的。
当然,有一支很大的团队参与开发,可所有重要选择都是我做的。所以从某种层面说,这些问题全都是我的错。我每天去办公室。当时我们做了一个在 Windows 右下角运行的小工具——我也不知道那种东西正式叫什么。它会在凌晨两点自动更新,把数据拉下来,这样我早上到公司时,希望本地已经是最新状态。
可它经常坏掉。或者你也经常不得不把它关掉,因为你正在本地改代码,某个 bug 还没修好,想第二天早上回来继续保持现场。
好,这个故事确实越来越长了。不过我先快速确认一下,才能跟上你的思路。
我会说,语言是问题之一。引擎处理资源的方式也是一个问题。“资源”(asset)是个技术术语,听你播客的人大概都知道,它指的是游戏要使用的任何一块数据:声音、纹理、地图、网格模型,诸如此类。
我特意解释,是因为我第一次听到这个词时根本不知道它是什么意思,却假装自己懂了,装了好几个星期,后来才慢慢猜明白。
对,我们在引擎设计上也本可以做出更好的选择,所有问题最后累积到了一起。不过,游戏完整编译一次可能也就两分钟,或者四分钟,我记不太清了。可 C++ 有一个潜在的问题。
如果你只改动一个文件,而且它正好是合适位置上的合适类型,又只是很小的改动,那就可以做增量构建,速度会快一些。但 C++ 里有一种到处共享的“头文件”,通常会定义游戏各部分共同使用的概念。比如我有某种实体,想修改这个实体的一项定义,很可能就得改头文件;一旦改了头文件,游戏的大部分代码甚至全部代码都要重新编译。真正要等上好几分钟的,往往就是这种情况。
而且是在我们已经花过精力、尽量避免编译太慢之后,仍然要等这么久。有些游戏做一次这样的修改,甚至要编译一个小时。我想大家都明白,这绝对是个大问题。
总之,回到 2013 或 2014 年前后。我开始对 C++ 极度不满。我当时想:电脑明明快得不可思议。你只要运行当时最新版的《使命召唤》之类的游戏,就能亲眼看到证明——屏幕上同时处理着惊人的数据量,画面非常漂亮,每个地方都在运行着色器。我以前也写过编程语言的编译器,所以我知道编译到底需要多少计算。
如果能把“抽象计算量”放在天平上称一称,编译器做的计算,远远少于游戏渲染一帧画面所做的事情。
当然,其中一个原因是 GPU 天生并行,可以更快地做很多事情。但另一个事实是:这些开发工具就是比它们本应达到的速度慢得多,而编程语言本身也比它应有的复杂得多。还有一部分问题来自我不断需要编写的各种工具代码。比如做游戏时,你得把实体写入磁盘、再把它们读回来,还得在编辑器里为它们提供用户界面。
编写这种代码时,系统必须知道实体有哪些字段。比如一个“位置”字段可能是几个浮点数;又比如它有一个纹理 ID,那么系统就得明白这个字段代表什么,才能在编辑器里弹出正确的控件。C++ 在这类事情上几乎帮不了你。也许过了十四年,他们终于开始往语言里加一点类似的能力了。
我一直在观察:好,作为游戏开发者,我真正遇到、真正让工作变困难的问题是什么?与此同时,编程语言领域的人又在讨论什么?我发现,他们声称要解决的问题,和我面临的这些实际问题几乎毫无关系。那我为什么不干脆坐下来,做一门真正解决我实际问题的语言,而不是去解决人们嘴里那些虚构的问题?说不定,它对其他游戏开发者也会有用。
所以我大概在 2014 年开始做这件事。那时我们还在开发《见证者》,它只是我的一个兼职副项目。《见证者》发售后,我们又花了几个月做后续支持和平台移植。到了 2016 年四月或五月,我才开始全职开发这门新语言,同时也启动了新游戏。
我有一个关于编程语言和 AI 的问题,不过不是你以为的那种。通常大家会问:“AI 擅长写代码吗?”你的答案大概会是“不”,我也猜得到。我很想深入聊这个,但可聊的东西实在太多了。这方面已经有大量讨论。所以我先把一连串问题拼起来,最后再落到真正想问的那个问题上。
我之前和我兄弟讨论过 ThePrimeagen 说的一些话。我想他之后可能也会来上播客。不知道你认不认识 Prime?
我们看了他的一些推文,然后开始思考:二进制、代码和整个编程过程里,到底有多少负担来自“必须把它们包裹在一套人类可读的语义里”?顺便说,我是外行,正在努力把这个问题讲清楚。我的意思你能理解吗?
那我的问题就是:编程语言的意义究竟是什么?它的意义在于,既能让人读懂,也能让计算机处理。它是一种让人类与计算机的二进制世界沟通的方式。
实际上不会。你的设想是不是这样一种假想界面:我只需要对 AI 输入要求,它在后端直接写出二进制;同时,它又能按照我的要求,把这些二进制以任意语言呈现给我。比如我可以说:“把你刚才写的二进制内容用 C 表达出来,好让我用自己熟悉的 C# 思维去读。”但真正送进游戏运行的仍然是轻量的二进制,不需要再用人类可读的代码包一层。
有很多原因决定,这种情况短时间内不会实现。首先,我们现在做这些事情主要依赖语言模型。我不认为语言模型是进行智能问题求解最有前途的 AI 形式。比如 AlphaZero——那个从零开始学会下棋、玩游戏的程序,所以名字里才有 Zero——它就不是语言模型。
它确实也使用了一些深度学习技术,所以两者有关联,但它不是靠把互联网上所有文本一股脑喂进去训练出来的,而是通过不断和自己对弈来学习。我认为,未来如果真的出现非常擅长编程的 AI,它的核心可能更接近 AlphaZero,然后再用语言模型和人类交流。
所以它会是多种技术的融合。可这里还有很多问题。先回到 LLM。
如果你让一个 LLM“帮我写一段 JavaScript 来完成某件事”,它返回给你的仍然是某种编程语言的源代码。所以,它现在并没有做到你描述的事情。你说的是一个假想的未来:AI 真正在写二进制,同时又能让人理解。
目前的问题是,每当它给你一段示例代码,那段代码都会依赖一些已有东西。比如 API,就是别人写好的一段代码所提供的接口,它已经解决了你问题中的某一部分。举个例子,假设我要做一款 3D 游戏。有人已经写了一段代码,可以替我画出一个三角形,那我就能反复调用它,画出许多三角形,最终在屏幕上组成画面。
现代图形系统实际已经不是这么简单运作了,但这是个方便理解的例子。问题在于,这些 API 本身也只能通过某种编程语言定义的接口来使用。拿 C++ 来说,它更接近你设想的情况,因为 C++ 程序最终确实会成为磁盘上的二进制文件;JavaScript 则通常以文本形式存在,每次加载时都要由浏览器转换成可执行形式。
可即使是 C++ 代码,也不是一组只负责告诉计算机“做什么”的纯粹二进制指令。其中大量内容都在定义怎样与其他 C++ 模块、与系统其他部分交互。因此,AI 生成的二进制至少也得模拟这些接口。可只要它还在模拟这些东西,那它在某种意义上仍然是由那门语言塑造出来的二进制。
除非未来有一天,我们完全跨过了这个阶段。我也不知道。但我想这样说:假如计算机聪明到只凭一句提示就能一次性把整个东西做完——比如你说:“给我做一款第一人称搜打撤游戏,战斗像《逃离塔科夫》,但别有那些毛病,网络连接也要很好。”你把所有要求列出来,它真的一次就能生成完整成品。我们会不会走到那一步?谁知道呢。
那当然太惊人了——惊人到我们所有人都没工作了,对吧?
但问题是,只要它不能一次做对,你要怎样逐步改进结果?你先试玩它生成的游戏,发现体验不是自己想要的。为什么不对?你可能说不清,只觉得手感不对。比如角色奔跑时,我想翻越窗户,动作却感觉又黏又卡。为什么会这样?为什么会产生这种古怪的阻滞感?
你对 AI 说“这里感觉又黏又怪”,它能明白你究竟在说什么吗?它能把问题修好吗?大概率不能。所以你需要某种自己可以查看的东西,才能弄清为什么会产生这种感觉。即使你不准备亲手编辑代码,中间有一份人类可读的代码表示,至少你可以说:“嘿,AI,我怀疑 vault_onto_window 这个翻窗函数读错了变量;或者我不明白它为什么这样做。你能解释一下吗?如果确实有问题,能不能把它修掉?”
所以在可预见的未来,这种编程仍然需要通过一步一步迭代来逼近目标。而作为人类,你必须拥有某种这样的中间表示,才能理解系统里到底发生了什么。
这非常有道理。好,我想关于这个问题,我没有别的要问了。
不,特别好,真的特别好。我们上次做播客时,评论区有人说:“托马斯根本跟不上乔纳森·布洛。”我当时就说:“对,确实如此。你处在另一个层次上,我甚至都不知道该怎么……”
编程本身实在太复杂了。你不能期待一个不是职业程序员的人完全——
我可以从零开始写 C#。这些东西我都会,虽然我知道在你看来这算不上什么。
但你平时并不是把大部分时间都花在写 C# 上,对吧?
好吧,那就不一样了。而且我得承认,你可能会因此讨厌我——我一整天都开着 GitHub Copilot。
那没问题。听着,只要它能满足你的需求——虽然这听起来有点怪——那就用好了。
这正是让我困惑的地方:它真的能满足我的需求。我不是夸张,在 Claude 开在旁边协助的情况下,我已经处理掉了测试玩家提交的一千个功能请求和 bug。它之所以对我有效,是因为我和团队已经用四年时间,从头搭建好了一整套 Unity 代码库。
Claude 加进来之后,就会这样工作。我保证,我不是想向你推销它。我只是在描述自己的困惑:我听你说它不擅长编程,也听 Prime 这么说;可我把它开起来,它确实在解决这一大堆问题。游戏仍然能以 60 帧以上运行。我知道代码大概变得更臃肿了一点,里面肯定也多了些会让你抓狂的垃圾。
比如,托马斯怎么都弄不明白,为什么测试玩家用手柄时,角色移动会发生抖动。我就可以问 Claude:“为什么会这样?”它会遍历我的所有控制器代码——武器控制器、相机控制器、角色控制器、物理系统——像是在为整个项目编写文档一样,把所有内容梳理一遍。然后它会说:“问题在这里。”接着真的把 bug 找出来。对我来说,它效率高得惊人。我不是在和你争论。
它真的非常擅长找 bug。而开发收尾阶段,这恰恰是我最耗时间的事情。试玩过程中可能有一千个 bug 要处理,你甚至不必先复现,只要告诉 Claude:“发生了这个现象,为什么?”
我觉得,编程里的情况其实分布在一个很宽的光谱上。你经常会听到一种老生常谈:“程序员 95% 的时间其实都在调试。”但对我来说,这并不是真的,原因之一是我已经积累了很多经验。
另一个原因是,我现在工作在一套自己非常熟悉的系统里。尤其当你使用自己的编程语言,而且大量通用代码也都是自己写的,你对整个系统就会异常熟悉。出问题时,你常常会立刻冒出一种感觉:“哦,我大概知道是什么了。”我以前在直播里就展示过这种情况。我会说:“我猜是这个东西。”然后过去一看,果然就是它。回到刚才的问题,我认为 bug 有很多不同类型,而 LLM 可能特别擅长其中某些类型,却不擅长另一些。
也许你的许多 bug 正好属于它擅长的那一类。我本来想把它们叫作“浅层状态 bug”和“深层状态 bug”,但“深层状态”听起来好像在说美国政府里的“深层政府”。总之,拿你说的手柄抖动问题举例。也许输入最初是整数,却直到太晚才转换成浮点数。谁知道真实原因是什么,但这种错误确实可能造成移动抖动。
这类问题的特点是,代码基本上一直都在做一件错误的事。只要查看源代码,并且足够敏锐,你就能看出哪里不对。
说实话,按照你的描述,我甚至有点意外 LLM 能找到这个问题。不过我们姑且接受这个事实。我自己遇到的那些真正耗时、难以解决的 bug,大多属于刚才所谓的——
——也不能真的叫“深层状态 bug”,总之,它们牵涉到非常复杂的游戏状态。编译器里也有类似问题:比如我们正在编译编程语言中的某个子表达式,其中有许多节点处在特定位置、彼此指向。诊断这种 bug 会非常耗时。
因为出错的原因可能是数据本身不对;也可能数据本身是对的,但它采用了一种特殊格式,触发了一组平时不会共同执行的代码路径。对我来说,真正棘手的往往是这些问题,而这似乎正好落在 LLM 不擅长的区域。
根据我使用语言模型的经验——我想这也符合很多人的经验——如果你刚开始一个项目,对它说:“帮我做个网页,放几个按钮,分别完成这样那样的功能。”
它确实能做到,而且大体上可以正常工作。剩下不能工作的地方,你再自己修一修。
但程序有一个特点:随着规模越来越大、复杂度越来越高,所谓继续编程、修改旧代码、增加新代码,本质上就变成了让新增的每一行代码都以正确方式与已有的一切保持一致。我们再拿实体系统举个简单例子。
《沉星之序》是一款基于网格的游戏。我们的坐标系统规定,每个方格宽度为一个单位,原点大概放在关卡某个角落附近。
游戏里有一个“玩法位置”,用浮点坐标表示,虽然这些坐标实际上会取整为整数,但为了方便数学运算,类型依然是浮点数。然后还有一个“视觉位置”,它会在方格之间进行插值,让角色移动看起来平滑。但因为这是一款基于网格规则的逻辑游戏,当你判断角色是否和某物碰撞时,不能使用视觉位置,而必须使用玩法位置。
所以后来写的任何代码,都必须理解这些决定,并正确地与它们协同工作。
甚至先不谈 LLM,这本来就是编程的核心难题之一:程序越做越大,你在修改它时需要始终记住、保持一致的约定就越来越多。只要其中任何一项没处理好,就会产生 bug。
随着程序越来越大、越来越复杂,这些约定会形成一张非常精细的关系网。你可以想象一张巨大而凌乱的蜘蛛网,把无数小部件连接起来:这个部件必须和另一个部件对“某件事应该怎样工作”达成一致,两者之间连着一根极细的线。软件工程的目标之一,就是尽量不让这张网变得过于混乱,但能做到的终究有限。
而游戏的魔力之一、游戏之所以有趣,恰恰在于游戏里的各种事物都会相互作用。这意味着它天然就是一个让各种东西混合、碰撞的系统。编程最终会变得困难,一方面是因为每次往代码里加入新东西时,都必须追踪越来越多的“蜘蛛网规则”,数量多到很难全部维持。
另一方面,代码越多,用来表示各种对象的内部状态也就越多。
这些状态会越来越复杂,而复杂度越高,状态出错就越容易。我发现 LLM 的问题在于,它们无法持续追踪所有这些——我好像还没说过“约束”这个词,但我就是这样理解的。为了让代码修改保持正确,它必须遵守大量约束。可很快你就会遇到这种情况:你让某个 LLM——我试过好几种——
对它说:“请加一个函数,完成这件事。”它会加好。然后你告诉它:“好,但因为其他系统有这些约束,我们还必须同时完成另外两件事。”它也许能大致照做,却不一定真的能牢牢维持所有约束。而且,当它试图同时处理太多要求时,就会开始忘记之前的旧约束。这正是编程之所以困难的原因。
它会逐渐丢掉以前的要求,最后你怎么提示也无法让它把事情真正做对。因为正如我刚才所说,它是语言模型,不是一个真正会下棋、会推演状态的系统。你真正需要的是一种类似棋类 AI 的东西,而我们现在并没有那样的编程 AI。每当你对 AI 作出这种评价,很多人都会立刻把它夸张成某种极端立场:“哦,你特别反 AI。”我根本不是这个意思。
我并不反对 AI。只要它确实有用,你当然应该乐于使用。我只是对很多人夸大它能力的说法感到恼火。当然,你现在就坐在这里告诉我,你使用它取得了很多成功。所以我也不知道,也许你的代码库里有某些特征,使它格外容易发挥作用。我说不准。也许我得等你的游戏真正发售之后再看,对吧?
我知道。我的游戏确实很“重”,在一些本不该吃力的地方也会卡,因为它看起来顶多像一款 2009 年的 AA 游戏。
我是说,那已经是最好情况了。不过性能优化本来就很难,这和 AI 没什么关系,对吧?
哦,你是说,按屏幕上的几何体数量来看,你希望它能运行得更轻松?
真正的问题是光照。Unity 的光照太糟了。默认情况下,每个网格模型都会投射阴影,每盏灯也都会产生阴影。如果你不是经验丰富的开发者,不知道阴影渲染会造成多大性能问题——
——你就会在场景里放入大量会投射阴影的点光源,然后性能立刻崩掉。你甚至没有意识到,点光源、聚光灯这类东西背后有多大代价。可如果你自己做引擎,我想你就不得不从一开始考虑这一切。
程序员当然知道这些问题,可一旦把工具交给美术团队,他们就会随心所欲地使用,对吧?
对。那我们继续吧。你大概还有 25 分钟吗?可以聊聊你的游戏,打开它给我们演示一下?
这款游戏的一句话卖点是什么?我很喜欢这样挑战开发者。你在 Steam 上的宣传语是不是:“它很复杂。”
我们确实试图在预告片里,把游戏的卖点压缩成最精炼的形式,所以我建议大家去看。不过,我也不确定九十秒的预告片能不能把一切说明白。这样吧,我先回到上一款游戏。《见证者》可能有些人玩过,它表面上和这款新游戏非常不同。
在《见证者》开头,你会解一些谜题。谜题面板上有各种抽象符号。游戏早期,你会不断看到新符号,却不知道它们是什么意思;然后通过实验,逐渐弄明白符号的规则以及谜题的解法。《沉星之序》在某种意义上也是这样。
开发《见证者》期间,我开始对一个想法产生兴趣:不同玩法元素结合后,可以生成更复杂的局面。我当时想:“如果我们不再组合简单的谜题符号,而是组合本身就复杂得多的东西,会发生什么?比如,把几款已经完整成立的游戏组合起来。”你现在看到的,就是游戏的世界地图。
游戏开始时,地图上有四片领地,每片领地都有类似标题画面的入口。它们分别属于四款不同的游戏。
进入这些领地后,你会发现每一个世界都有完全不同的玩法机制。
此外还有一个庞大的世界地图,供你探索和揭开各种内容。你会向外冒险、驱散迷雾,发现越来越多的东西。但在游戏初期,你探索到的一切都会属于这四片领地之一。比如我现在进入 Mirror Isles——哦,等等,这里先跳过吧。我把某些东西关掉了,这里只是以后要做的一段过场动画的临时占位。
顺便说一下,这个关卡现在用的是临时画面,已经非常旧了。上一个关卡的美术比较好,只是我想跳过那段假的过场。
这个世界的核心机制是传送,你会在不同位置之间瞬移并解决问题。
哦,我太喜欢那个传送效果了,着色器和粒子都太酷了。
里面还有一些很有趣的惊喜,我不想剧透。最基本的玩法包括:把东西推进水里、移动镜子、传送,以及解决谜题。这个世界讲的是某个角色在处理一场特殊处境,而整个玩法都围绕镜子展开。
如果往这里走……其实我正在想,怎样才能在演示几个关卡的同时,尽量避免剧透。
还是那句话,乔纳森,任何你不想保留的内容,我们之后都可以剪掉。
不用,没关系。这里真的很旧,是早期临时概念美术,和最终方向并不一致。不过这是另一个世界,里面有不同的角色。这四个世界都基于我们很多年前、项目刚启动时就已经做出来的几款游戏。
那些原始游戏当时甚至可以直接在网页上免费玩。例如 Mirror Isles,大家可以自己搜索。等等,我不知道为什么游戏现在卡住了。总之,这些世界都来自已经存在的游戏,我们的想法是把它们组合起来。这里是《Heroes of Sokoban》——它由 Jonah Ostroff 使用一种叫 PuzzleScript 的语言制作。好,现在怎么回事?
我怀疑现在的游戏采集方式干扰了音频。它可能在尝试抓取声音,结果字幕的时间轴就不再继续前进了。
所以画面像是彻底冻结了。我们得把这个问题弄清楚。不过这倒是一次很好的测试,因为以后会有主播不停地直播这款游戏。
对,我们必须保证这种情况没问题。我平时用 OBS 采集时一切正常,但现在这套配置里有某个东西出了问题。这里涉及一个大家可能知道的细节。
你其实无法精确知道声音会在什么时候真正播放出来,因为音频系统使用的时钟和其他系统略有不同。
如果你只用 CPU 的时钟计时,两者就不会完全吻合。所以通常的做法是直接向音频系统查询:现在播放进度到哪里了?
可这样又会留下一个问题:如果因为某种原因,音频采样没有真正输出,音频时钟也就不会向前走。于是这个角色的字幕就停住了。这是我们需要解决的事情之一。好,回到游戏本身。这个角色是一名战士,可以一次推动任意数量的方块。他生活在一个有点像《龙与地下城》的英雄世界里。
每位英雄都有类似 D&D 职业能力的“解谜技能”。关卡里也有你会预期看到的地板按钮之类的东西。比如,我可以用方块压住这个地板机关。
我只是在跳关。按一个开发者快捷键,就能在关卡之间前后切换。
太棒了。乔纳森,我快速问个问题:你刚才那个灰盒关卡,是不是每个关卡在开发初期都会经历的状态?
你是说设计阶段吗?对。我快速打开编辑器给你看。如果我要编辑这个关卡,可以直接添加墙壁之类的东西。等等,现在编辑器还处在游玩模式。
对。在编辑器里,如果我想立刻试玩正在编辑的内容,只要按 Ctrl+F11,它就会直接在游戏里运行。
这太让人混乱了,和 Unity 完全是另一套范式。
当然,我根本不知道 Unity 是怎么工作的。我只知道在 Unity 里,你按一下“播放”,然后等二十分钟,游戏才终于启动。
这只是我们早期对方向的一次概念尝试,和最终目标并不匹配。随着世界观、世界内容逐渐成形,很多东西都会改变。而且它本身的精细程度也还不够。在继续之前,我给你看一下——
你们是什么时候意识到,利用高度差会给这款游戏带来很大的视觉优势?
其实没多久,大概一年前。听起来好像很久,但放到整个开发历程里,这是非常新的变化。
对,这些只是示例。我可以回到编辑器里的某个位置。其实我自己用编辑器时,主要编辑的是玩法对象,而不是视觉对象,所以操作起来可能会有一点……
对。不过它只是一套引擎,并不是完全通用的工具。像 Unity 或 Unreal,即使团队里没有程序员,你也有可能做出游戏。
用我们的引擎,你还是得会编程。不过也许你的 LLM 可以替你写,那就没问题了。我也不知道。
可它是用 Jai 写的,我觉得 LLM 未必会啊。
不,它其实会。你只要问,它确实能写出一些 Jai 代码。网上已经有足够多的示例了,只是训练数据不像 JavaScript 那么丰富。我们还会在关卡里直接留下备注。比如:“嘿,如果你要为这里制作美术,请务必保证这个洞仍然清晰可见。”
我们还可以随机化怪物之类的东西,不过我忘了具体怎么操作。
我连这个功能怎么用都忘了。它其实还没有名字。等免费发布时,显然得想一个,但现在我还不知道。总之,我每天都在用它,很多操作已经成了下意识习惯,反而很难现场解释。
有一个细节让我有点自豪,只是在这个场景里不太明显。我找个别的关卡给你看,我们的水体效果很不错。
你会注意到,我们非常努力地维持网格的可读性。正如一开始所说,我希望游戏始终容易读懂,但又不能难看。我们有一种可以直接“绘制”网格显示强度的功能。我平时不是经常做这个,不过如果打开绘制面板……我忘了具体是哪条通道。3D 渲染里常见的一种做法,是借用传统颜色通道来表示新的数据,因为底层数据就是这样组织的,GPU 也最擅长这样处理。
我想应该先选中对象,再按 T。哦,现在我确实在擦除一些网格线。
对,就是这样。我也可以重新画上一些,只是现在笔刷强度很低,效果很淡。
实际上,网格使用了一张动画翻页纹理,上面再叠加一张控制强度的纹理,可能还会乘上一些噪声。近距离看也许不明显,但网格上还有类似 3D 法线贴图的效果。水波经过时,网格本身看起来真的会向上凸起。
这虽然不是真正的等距视角,但看起来有点像,对吧?你会不会经常产生一种冲动,想展示关卡的所有角度,让相机转起来、插入过场动画、拉近镜头,然后从各个模型旁边飞过?
我们没有太多过场动画,但有些关卡的几何结构会非常复杂。我们确实有一些关卡提供多个观察视角。
我找一个。这个关卡应该比较简单。你拿起这张地图后,会获得一个替代视角;这里就是纯粹的正上方俯视。它可以帮助玩家读懂关卡。在其他关卡里,我们有时也会提供这种俯视视图,让你更容易看清东西的位置。所以我们偶尔会这么做。
但我还是想看不同角度。我想把镜头降下来,看看那根管子。
问题在于,如果允许你把镜头降下来近距离看管子,我们就必须把管子做得足够精细,经得起近距离审视。我们并不想承担这种成本。而且我自己玩解谜游戏时,也不太喜欢随意旋转相机。有些游戏会直接把手柄右摇杆映射成环绕旋转镜头。
从玩法角度说,确实没有必要。只是我作为美术工作者,总想看看所有东西、看看每个组件。
我觉得我们的美术团队在只需要处理少量视角时都松了一口气。他们会说:“好,我们不用担心从那个角度看起来怎么样。”
当然,它只需要在正式相机角度里看起来正确。我知道这背后全是障眼法——而且确实有字面意义上的烟雾。
真的是“烟雾与镜子”——字面意义上的烟雾和镜子。这个烟雾效果太惊人了,哇。
光源照进烟雾里的方式之类,效果都很不错。最终实现它可能并没有特别困难,但我们经历了很多轮迭代和猜测,才找到现在这个结果。
所以你是说,你们大概一年前才真正找到怎样为这款游戏营造纵深感?因为你刚才给我看的旧画面非常平,而现在完全是另一回事。
这就是我说的:找到一款游戏真正的视觉风格,需要时间。我们到底在做什么?应该怎样做?其实我可以稍微讲讲这个效果是怎样实现的。
这是我刚才跳过过场动画的那个关卡。天啊,它又卡住了。如果切换到设计师模式,你会看到这些岛屿,中间隔着一些水。
这个关卡基本是对原作的直接转写。Alan Hazelden 设计的 PuzzleScript 游戏《Mirror Isles》里,就有一模一样的关卡。我们一开始只是把它做成 3D 版,也许稍微调整了一点岛屿形状。
所以这算是在向原作致敬?这个关卡真的会出现在正式游戏里?
没错。玩家一开始会原样体验它,之后玩法才逐渐变复杂,并和其他机制融合。那这些岛屿到底是怎么做出来的呢?
答案是,我们准备了若干种独立的小块模型。比如这里有一小块,我们直接把它压到其他块上,然后用一些方法把法线混合在一起,主要由着色器处理。否则,只要两块模型的坡度略有差异,你马上就会看出它们其实是两个互相穿插的团块。
但现在你看不出接缝。你还能看到,我们在上面放了许多小型细节模型。
目前都是手工摆放。理论上可以做一个模式,让系统自动撒上这些细节,但我完全不知道怎样才能让结果足够好。
美术风格的另一个核心要求是:岛屿必须显得有机。否则,既然最后仍然只是这种方方正正的立方体,我们何必投入这么多精力做漂亮美术?所以它不能真的只是方块。
但它又必须接近方块,因为玩家不能对“哪里可以走”“哪里能推动物体”“接下来会发生什么”产生歧义。
因此,我们做出了一种有机、自然,但仍然严格尊重网格的视觉风格。这一点非常重要。你还会注意到,所有细节物体也都在强调网格。比如这些小植物,实际上勾勒出了方格的边缘。
对,都是美术手动摆放的。除此之外,还有一层贴花系统。关卡打开时你看到的这些图案,全部都是投射式贴花。懂图形技术的人可能知道这种功能。如果我抓住这个贴花移动,你会看到我正在挪动一条很大的拐角线。
它和底下的网格模型相互独立,只是像印章一样投射到表面上。你也可以随意缩放。
对。即使我把这块模型抓起来……它会随着移动继续投射。我们把这个平面旋转一下。
这是一种非常好用的方法。以前,如果纹理直接画在模型上,而你在场景里重复摆放同一个模型,就会一遍又一遍看到完全相同的纹理,形成很难看的重复图案。现代游戏通常会尽量避免这种效果。当然,你也可以把它变成一种刻意的复古风格,故意留下大量机械化、计算机感很强的重复,但那不是我们的目标。所以许多岛屿的底层其实真的只是一些矩形。
我们用稍显凌乱的方式重复铺设这些矩形,再在边缘围上其他部件,然后利用贴花、光照等效果把它们融合到一起。
固定相机的美妙之处就在这里:你似乎不用特别担心优化,可以把各种资源疯狂塞进场景里,我觉得性能不会有什么问题。
我一开始也是这么想的。结果有些时候还是会遇到问题,主要和 draw call 有关。随着引擎不断开发,我们逐渐把它调整成了另一种架构。
比如这个场景就更复杂一点。你可以把下面这个平面想象成刚才那座岛,然后上面又有墙壁等结构,所以整体更加立体。那这个场景里到底有什么?首先有一些玩法对象。
有角色、镜子、一些光源。但实际上,场景里几乎所有其他东西,都属于一种叫 Inanimate 的实体类型。它基本就是一个网格模型,附带一些颜色,以及极少量其他字段。你也可以覆盖它使用的材质之类。
如果统计场景中的 Inanimate,大概有一千个。你眼前几乎所有可见物体都属于这一类。所以我们意识到——
它们是静态对象吗,乔纳森?就类似 Unity 里的 Static?
大概可以这么理解。这些物体本身通常不会移动,但有些材质会运行动态着色器。比如我不知道这里有没有开启风,看起来好像没有。可如果创建一个风力实体,这些植物就会随风摆动。
对,是着色器效果。对象本身可以是静态的,着色器却可以动态变化。
后面那个东西大概是粒子系统,属于另一种实体类型。还有这些小铃铛——哦,它们刚才不动,是因为我们其实没有进入游戏模式。好,现在动了。
你可以看到它们在轻微晃动。它们属于另一种实体类型。动画本身并不复杂,我们把它叫作“程序化动画”。它不是物理对象,也不会真正参与物理交互,只是按程序进行动画。
它不会和其他东西相互作用。重点在于,既然最终要渲染的几乎所有内容都属于 Inanimate 类型,那么关卡加载后,我们可以把它们全部放在 GPU 的同一个缓冲区里,每个渲染通道只用一个 draw call 就画出来。当然,实际还有很多渲染通道,包括光照叠加、粒子等。
许多游戏首先会执行一次深度预通道(depth pre-pass),目的是确保同一个像素不会被昂贵的着色器反复绘制。
我们也这样做。我们的主体是前向渲染器,不使用那些非常复杂的延迟渲染方案。不过我经常和别人争论,到底什么才算“前向”、什么才算“延迟”。毕竟我们确实也会使用一些离屏缓冲区来实现特效。我可以快速切换几个调试模式。现在这个画面只显示所有纹理的基础颜色。
这个模式显示用于光照计算的法线。红色大概表示 X 轴方向,蓝色表示向上。我想它可能在几何法线基础上做过调整;也可能几何法线原本处在对象空间里,我记不清了。
“顶点颜色”就是我刚才在海面绘制时写入的那些通道。在海水上,我们用它控制网格线;而在这些物体上,它用来混合不同材质。
我们现场试一下。正如我说过的,我平时不做美术,但我试着像刚才处理海面一样操作。我打开绘制面板,拉近镜头,看看能不能改变它们的外观。等等,我得先选中它们。好,我想选中几块。你看,我可以这样——
其实这项技术可以追溯到很早以前。我记得《神秘海域》第一或第二作曾经在 GDC 演讲里谈到过类似做法。基本思路是,提前制作一组彼此对应的材质。比如我有一种崭新的木材,也有一种风化木材。绘制时,只是在二者之间做交叉渐变。这是最简单的两材质混合,当然也可以同时使用更多材质。
我们的材质系统里,blended_two 会在两张纹理之间混合,blended_three 会混合三张纹理,以此类推。你可以调整不同颜色通道来控制混合。现在我编辑的是红色通道,所以结果显示在这里。
绿色通道里有东西吗?没有。我现在画绿色,画面没有变化,所以这大概是一个只混合两种材质的 blended_two。你可以想象,在过去,如果想做出大量变化,就必须制作许多不同网格,或者生成许多纹理。
而现在,我实际上可以反复使用同一批网格模型,这对控制游戏安装体积很有帮助;然后只在额外通道里写入变化数据。我们切回刚才那个模式——它没有把名称显示出来。这里就是顶点颜色模式,能看到我刚刚画过的位置。
你可以直接看到笔刷正在写入数据。它只是传给着色器的若干通道之一,最后由着色器完成混合。提醒我千万别把这个被我画得乱七八糟的关卡提交进版本库。
我懂,对吧?还有,你什么时候必须走就直接告诉我。我可以一直聊下去。
我再快速看一个。这个是粗糙度贴图,决定物体怎样响应光照。
假如这是一款开放世界游戏,场景里到处都是这些……唉,我姑且把它们叫作 splat map 吧,我也不知道准确术语。总之,就是用各种遮罩制造纹理变化。那性能会不会变成一场噩梦?
我觉得大部分都不会有问题。这里很多技术和我们在开放世界游戏《见证者》里采用的做法相似,或者说是从那些技术发展而来的。
例如,我们现在看到的是光照贴图。这里还有些问题,比如某些树没有烘焙进光照贴图。不过总体来说,在 Unity 里你可能会打开环境光遮蔽,例如屏幕空间环境光遮蔽,来补充一些细节。
这里其实也有非常轻微的屏幕空间环境光遮蔽。但像下面这片更大范围的阴影,则属于全局光照效果。
对,这是烘焙光照。现在 Unity 里肯定也有相应做法,不过也许不是所有游戏都会采用烘焙式实时——不,是烘焙式全局光照。
肯定有。不过这套技术我们在《见证者》里就用过。刚才给你看的那种材质混合技术,在《见证者》里也有某种版本,只是输入更少、实现可能更简单。这里最昂贵的部分也许是我刚才展示的贴花,但远处把它们渐隐掉就行。至于开放世界里到处都有大量光源,这就是经典难题了:你必须想办法管理它们。
在非常古老的游戏里,GPU 直接进行光照计算时,往往一次最多只能处理八盏灯之类的硬限制,你必须围绕它设计。现在更多是另一类问题:我要把会影响某个物体的光源分组归箱;同时要保证着色器在处理一定数量的光源时足够快,也要避免分组过程本身拖慢渲染,诸如此类。
另外,还有你刚才提到的问题:光源一旦需要投射阴影,那又完全是另一回事。
我们现在看到的这些阴影,大部分是烘焙阴影,角色阴影除外。好,这里既有阴影贴图,也有光照贴图。那些轮廓更清晰的阴影实际上是动态的。比如我选中太阳实体——它怎么跑到那边去了?总之,我可以实时改变这些阴影。
不过我移动太阳以后,原先的光照贴图就失效了。它们目前还在那里、也仍在被渲染,但我们会根据正确的光照重新计算。哦,还有一项很重要的东西我忘了展示,大家可能也在别的引擎里见过。是哪个面板?这个吗?
是这个。好,这里只是另一种查看方式。哦,这个面板后来加了很多东西。刚才我是按快捷键在不同模式间切换,这里也可以直接选择,而且模式更多。这个是光照贴图,也就是烘焙部分;这个是光照探针。两者作用不同,但会共同构成场景的最终光照。
所谓光照探针,大致就是烘焙时把“相机”放在场景中的某个点,把周围环境记录进立方体贴图,然后附近的物体使用这张立方体贴图。我忘了哪一个模式能显示探针……哦,是这个。
这些球体中的每一个,都是场景某个局部位置的光照采样。附近的网格会使用对应的立方体贴图。美术人员会根据判断,把探针放在最有帮助的位置。我认为光照贴图和光照探针至少得有一种。单独看这个通道时画面确实有点难看,哈哈。哦,我想还可以这样。
现在我们可以看去掉那项效果后的完整场景。这是关闭光照贴图的样子,可以看到画面很平。
这是关闭光照探针的样子,倒没有那么平。看来光照探针帮了很大忙,只是在树叶之类的位置表现没那么好;而光照贴图很擅长补充那些细节。
不,它们影响所有东西,所有物体都会受到影响。这只是着色器里的处理方式。
在 Unity 里,光照探针不会影响已经烘焙的静态物体。只要某个东西有烘焙光照贴图,光照探针就不会再对它起作用。
哦,明白。或者严格说这可能并不符合物理规律,也许我们其实是做了平均之类的处理。
总之,两者缺一个也可以运行。我们刚才在美术上花了很多时间,不过我想说明,这并不是因为我只关心这款游戏的画面。
我确实非常在意美术,所以才会一直追问。但我也关心玩法。我们能不能快速聊一下玩法?
我特别着迷于“能不能用一句话推介一款游戏”这件事,总喜欢逼开发者尝试。
其实这次我练过很多了。几周前做了一大堆媒体采访,反复回答这个问题。我试着概括一下,不过说实话也有点说累了。好,核心想法是:游戏设计的魔力之一,在于游戏为什么会好玩。不同游戏有不同原因,但设计师在设计时会重点处理其中一件事。在解谜游戏里最容易看出来,不过它其实会影响各种类型的游戏:那就是设计出能够彼此良好配合的对象。
在解谜游戏里,可能有一面能够传送物体的镜子,再搭配另一个能与它产生有趣互动的物体。但所有游戏都是如此。比如第一人称射击游戏里,你设计了若干枪械和敌人:用这把枪攻击这种怪物,会不会形成有趣的局面?把怪物 A 和怪物 B 放在同一个房间里是否有趣?换成 A 和 C 呢?
游戏设计大体就是这样。我想做一款把镜头拉近、专门审视这种现象的游戏,试着理解:不同事物彼此组合并创造出令人愉快的局面,这到底意味着什么。因此,我们在这款游戏里准备了四个世界。
玩家先分别游玩它们,然后我们把它们揉在一起,让玩家开始体验不同世界之间的组合。
接着,我们会带玩家经历这些世界各种各样的排列组合。当然,我们也会尽最大努力把关卡设计得好玩、令人惊喜。
最终目标,是把聚光灯打在游戏的这种乐趣上:一些东西组合起来,生成了出人意料的局面;可仔细一想,你似乎又本该预料到,只是当时没想到。于是它带来惊喜和快乐。这就是整款游戏最根本的主题。
它有点像元素系统,比如火、冰、水、土,只不过这里对应的是不同玩法。假设一个人先掌握了“火”——
我不是说游戏里真有这些元素。我的意思是,一个人先掌握火,然后进入水的世界,再掌握水。等把两者组合起来,就会出现一整套全新的玩法风格。大概是这样吗?
你可以分别学习火和水,但显然水与火会相互作用。你可以把水泼到火上将它熄灭,而如果你一直只在“火的世界”里玩,就不可能知道这件事。
可水浇到火上还会产生蒸汽,可能烫伤你,也会产生烟雾;它还可能改变被火烧过的表面颜色,这些都未必是你单独观察某个元素时会注意到的。而且,“水的世界”里也许不只有水,而是包含各种液体。
也许其中还有汽油。你在水世界里只觉得它闻起来怪怪的;因为那里没有火,所以它看起来不过是“有怪味的水”。等两个世界合并后,你才意识到两者其实截然不同。
所以目标是让玩家按线性顺序逐一掌握:先从一个世界开始,熟悉它,再进入下一个世界并掌握那里的规则。
我往外走一点给你看。以那个 RPG 英雄世界为例,我们刚才展示了战士,但还有能拉动物体的盗贼、会传送的法师、能魅惑人类和怪物的吟游诗人、能转化物质的德鲁伊,以及提供保护的女祭司。这个世界大约有六名主要角色。你在世界地图上从一个画面走到另一个画面时,会进入不同关卡,让这些角色发挥各自的能力。我刚才本来应该演示一下,不过现在已经跳到后面了。
这期播客已经聊得很久了。总之,你会穿过这些画面,不断向更远的地方冒险。
然后在某个时刻,你会差不多抵达尽头。到这里、并完成这个画面时,这一片区域基本就算结束了。当然,并非所有关卡都必须完成,有些是可选的。我现在已经在世界地图上向北走了相当远,而北方的所有领地都属于这个 D&D 英雄游戏。也就是说,这里像是四款不同的游戏。
它们起初有点像收录在同一部作品里的四篇选集,但后来会真正融合起来。
太疯狂了。所以你是把四种不同的游戏类型揉成了一款游戏?
某种程度上是。我更愿意说,它们是解谜游戏的不同子类型,不过你的理解基本没错。
这是预告片里也展示过的一部分。我们刚才在北边看了不少英雄世界的内容,再快速看一名角色,你就能明白了。我现在只是按作弊快捷键,直接跳进不同关卡。这个人是法师。我们做了一件很有趣的事:同一关会用不同方式反复出现。这就是你刚才见过的那一关,只是换了一名角色。
刚才见过战士,他能推动物体,而且一次可以推动任意数量。然后是盗贼,她完全推不动任何东西,所以物体对她来说相当于墙;但她可以拉动物体。拉东西是她性格中一种近乎强迫性的冲动,所以她在这里不能直接向右走,而是必须先把东西拉走。
至于法师,他会传送,而且只要条件允许就必须传送,因为他对自己的传送能力极度着迷,甚至有点执迷不悟。所以他如果试图从这里往左走,就会直接和那个物体交换位置。
接下来的一些关卡会一次组合两名角色,这里则是同时使用三名角色。结果会形成一种“错误连锁喜剧”。我们刚才短暂见过这个地板按钮:站在上面,门就会打开,我就能出去。可是……等等。我们又不能让某个角色一直站在按钮上,否则那个人自己就出不去了。
所以我们得拿到角落里的水晶。我可以让盗贼绕过去拉它,但她不能把东西拽过拐角,因为物体始终只能紧跟在她身后。那就让法师去把它传送过来。
可法师一试图往南走,就和战士交换了位置,把自己卡在这个小隔间里。于是战士必须下来,让法师和他交换,再和盗贼交换,最后把物体弄过拐角。现在盗贼又可以继续拉,可她自己又卡进了小隔间。如果法师回来帮忙,他又会把方块传回去——不过没有回到最初那么远——于是盗贼还能再拉一次。谜题就是这样把不同角色的能力组合起来。
游戏早期的谜题在概念上还不会特别深,因为玩家仍在学习每种能力及其运作方式。但随着进度推进,谜题会越来越强调出其不意。好,再展示一个有趣的东西。刚才看过角色了,现在看看世界地图上的推进方式。起初,它有一套比较常规的解锁机制。例如我用开发者快捷键直接把这一关判定为完成,这条路就打开了。
可一旦玩家掌握了基础机制,探索和推进就会越来越依赖你在关卡里学到的概念。你在关卡中看到“法师的传送以某种方式运作”,之后就要把这个知识运用到世界地图上。英雄区域里,我们用这些衣柜实现这一点。刚才还没有介绍玩家在世界地图上控制的角色:她与四款游戏里的任何角色都不同。她可以走进衣柜,换上服装,从而获得对应角色的能力。
所以她可以变成法师,拥有传送能力,但也会像刚才关卡里的法师一样被卡住。嗯,假如我想抵达右边的关卡,可以先变成盗贼,把这个拉过来;再变成战士,把它推到某处,依此类推。世界地图上的推进会逐渐变成这种形式。回到你刚才的问题:当我沿着线性路线一路向北走到这里时,我理应已经完成了足够多的英雄关卡。现在我开着作弊模式,就厚着脸皮直接穿墙过去。
我现在处于作弊状态,否则从这条龙面前走过会被杀掉。正常情况下,我会先解开这里,绕到后面的通道。这样就能打通另一条连接这些房间的路线,会方便很多。南边就是刚才那两个房间;与此同时,我还会接触到这个金色房间,可以通过——
——结合两个世界的机制来解决。这里稍微有点剧透。介意剧透的观众可以快进;反正节目也快结束了,直接按停止也行。不过我并不太担心剧透,因为游戏非常庞大,惊喜实在太多,被提前知道一件事也没什么关系。重点是:如果我已经在英雄区域一路解谜,抵达这条后巷,就意味着我基本掌握了所有英雄角色以及它们的运作方式。这里还有一个衣柜,我可以把它拖来拖去。
这里有一个地板按钮。我想穿过那些门,但三扇门的开关状态彼此相反,不可能一次全开。好吧,我至少可以先把水晶压在按钮上,于是其中一扇门打开,我能走到这里,可接下来怎么办?顺便说,这一带是快速旅行区域,会随着你探索更多内容逐渐实体化。
假如我去另一边——当然现在还是在作弊——如果我在 Mirror Isles 完成了一系列谜题,就会来到这里,打开通往这边的道路。然后你会看到这面位置格外显眼的镜子。完成这些关卡后,镜子上的冰会融化。
还记得我在 Mirror Isles 里怎样用镜子传送角色吗?这里可以对水晶做同样的事。于是我不必再亲手碰水晶,就能在两个位置之间切换它。回到这里后,我先用盗贼能力把水晶放到合适位置,再用镜子远程切换它,就能真正穿过这些门。
接下来这个画面我只展示一下,因为预告片其实已经有点剧透了。假如我……怎么回事?哦,按错了。假如我清除所有迷雾并把镜头拉远,就能看到整个地图的规模。
不,不,没关系。只是你仔细看的话,会发现有些区域明显还是方块占位,美术还没完成,所以请自觉把视线移开。
预告片里我们用迷雾盖住了那些地方,因为它们还没有做好。
其实我现在就能把迷雾打开。预告片迷雾——好,现在所有东西显然都“完成”了,对吧?
我们现在已经有测试玩家接近通关了,所以它确实可以完成。
没有。事实上,正式玩家拿到的版本反而会更容易,因为这些测试者一路面对的是有 Bug 的关卡、存在漏洞的关卡,以及各种尚未修好的东西。所以,确实有人能通关。我们非常清楚:自己做了一款超级庞大的游戏,这对想玩超级大作的人来说很好,但——
——并不是每个人都愿意报名加入“解谜大军”,对吧?哈哈。所以,对于那些并不想挑战“史上最大解谜游戏”——当然也有其他作品可以竞争这个称号,总之就是一款非常庞大的解谜游戏——的玩家,我们设计了多重结局结构。
游戏有三个结局。第一个结局并不要求你把整款游戏一丝不漏地全部玩完。它是一个完整、令人满足的好结局,但不需要完成所有内容。
它令人难以置信,而且看起来确实花了很多——花了很多钱。
不不不,真的太厉害了。你刚才展示的内容也让人看清楚:引擎和游戏本身的开发共同构成了这段十年旅程——引擎、游戏,还有那门编程语言。
好的,各位,愿意加入愿望单的人可以点简介里的链接。让愿望单数量涨起来吧。
愿望单当然非常重要。我们还有一个 Discord,大家可以进去和其他人交流。我之前试着从 Twitter 分享链接,结果 Twitter 把链接重写了,最后打不开。不过 Discord 确实存在;游戏也有自己的 Twitter 账号,大家可以关注这些渠道。
评论区
共 1 条评论热门最新