来源:游戏研究社

游戏代码的道与术。
今年我玩了近百个小时的《哈迪斯2》,其中一部分时间是在游戏的文件夹中度过的。
乐趣在于,《哈迪斯2》的大量核心逻辑、技能数值和关卡流程都是用Lua脚本编写的,这些文件直接以纯文本形式存在于游戏目录中,可读性很高,任何玩家都可以轻松阅读、理解。
换句话说,进入磁盘文件寻找contents/scripts,这其中的将近480个文件、50多万行lua代码,就像一本细致的游戏设定集,让你能够深入了解游戏的各个系统包含有哪些内容,又是怎样运作起来的。
比如说,众所周知“哈迪斯”系列以文本量大著称,十分注重剧情故事和人物塑造,而在这些文件中,就可以找到所有角色的全部对话。
对剧情有兴趣的玩家在翻看时,得做好“剧透”的准备清晰易读的另一个好处是,不仅便于开发者后期对游戏的维护和拓展,同时也给与玩家更多操作的可能——因为游戏数值清晰可见,所以修改起来无非就是改动下数字,几乎不费功夫;Mod作者也不需要进行复杂的逆向工程,还能结合开发者留下的注释作为教程,难怪游戏在玩家社群中被称为“对Mod”最友好的游戏。

12月刚刚在玩家社区引起热议的人气Mod《扎格列欧斯之旅(Zagreus Journey)》就是个挺典型的例子。
这个大型Mod允许玩家直接操纵2代主角墨利诺厄重新体验1代的全部冒险,不仅全面复刻了1代的关卡、敌人,还调整适配了战斗机制,全面支持阿卡那牌、忠誓任务、信物等系统,新增了数十种收集资源与大量剧情故事。

如果不是《哈迪斯2》的“代码底子”足够好,很难想象MOD作者能够单枪匹马在不到一年的时间里完成这么大的工作量。
这当然是游戏的开发商Supergiant Games有意为之。早在2020年的初代《哈迪斯》时期,其就在与玩家交流的问答环节提及:“游戏的许多方面都很容易修改,因为数据都是公开的。”玩家能够更改所有的文本和数字,并为游戏自由添加内容不受限制。
而哈迪斯的口碑和热度延续,似乎也一定程度论证了“好代码”的积极作用:不论从日后持续迭代游戏或是激活玩家参与内容创作的角度,这些“背后功夫”都不是白做,还能够赋予作品更广阔的成长空间。
所以说,游戏开发者有什么理由不去尽力优化代码呢?
1
还真有。或者说,代码“能跑就行”,至今仍是游戏行业中的一种普遍论调。
2024年的《小丑牌》拿奖拿到手软,俨然被行业视为风向标,但其游戏代码却远不如游戏设计那么优美,许多复杂的游戏逻辑,如不同小丑牌的效果叠加、分数计算,都是直接用大量的、嵌套的if-else语句堆砌而成,导致代码看起来原始且重复。


游戏开发者LocalThunk曾经直言不讳《小丑牌》的底层代码是用“希望和梦想粘在一起的”,颇有些“俺寻思这可以,没想到真的能行”的自嘲意味。
当时也有不少遗憾的声音,表示这样的底层代码使得《小丑牌》难以随着时间的推进进化、拓展机制。
然而在相关讨论中,经常是支持者占了上风。一方面,大量的if-else语句在代码效率上固然不算好,但同时也具备容易理解的优势,这使得玩家能够相对轻松地在核心玩法框架不变的前提下添加新的小丑牌。
另一方面,不少游戏开发者都站出来解释,如果代码能够正常运行,那么就没必要钻牛角尖。例如一位曾供职过R星的独立开发者就表示:“要记住目标是发布游戏,而不是编写最简洁、最优雅的代码。”

这些支持者大多认为,只要代码能跑,便于调试,并且没有严重影响性能,那就已经合格——大多数情况下,只要达成上述条件,玩家也不会在意游戏背后的代码如何运作。
就说飞没飞吧事实上, LocalThunk最终也是这么达成了自我和解:“它并不完美,但我知道每个东西在哪里,而且我是唯一需要维护它的人,所以这对我来说很有意义。如果它很蠢但是有效,那么它就不蠢!”
LocalThunk原本就只是一位业余游戏开发者,在游戏开发过程中神经一直绷得很紧。根据其自己发表的开发记录,《小丑牌》完成之前,他已经长期焦虑、失眠,甚至一度因焦虑症发作去了医院。
可以想象,在开发者光是为了构思创意、实现创意就已经费尽心神的情况下,很多时候是无暇顾及“精修”代码的。
不是所有人都拥有高超的编程技术,对于创意工作者,花费时间在代码上,往往意味着打磨创意、填充内容的时间被挤占。
真要以代码水平去要求《小丑牌》的话,此消彼长下,游戏的创意水平大概率达不到今天的高度,甚至连游戏能否正常发布都得打个问号——这其实是大多数独立游戏都会面临的问题。
很多玩家今天耳熟能详的作品,实际上都充当过编程的反面教材。《传说之下》作者在处理对话系统时使用了一个巨大的switch语句,导致游戏中的每一个对话分支、每一个角色的每一句话,几乎都堆在一个几万行的超大函数里;《蔚蓝》的主角控制逻辑包含了超过5000行代码,攀爬、跳跃、冲刺、物理判定、动画切换,全部挤在一个文件里;初代《我的世界》的Java代码也是出了名的随性混乱,致使游戏底层架构臃肿,后续花了多年时间重做。

知名程序员、id Software创始人之一约翰·卡马克曾举证:“我儿子说‘写代码不过是if、else和for循环而已’”
离中国玩家更近的一个例子或许是《太吾绘卷》。对不少国内玩家而言,这是一款具有划时代意义的产品,感情很深,既是因为它当初闪电般的迅速崛起,也是因为在那之后对游戏正式版的漫长等待。
不少人可能还记得,回望2018年,《太吾绘卷》的代码水平最初是被当作神话或是传说来传播的。游戏制作人茄子只看了一个月Unity教程就上去写游戏,结果“蛐蛐大神保平安,绿皮逆练代码无BUG一遍过”,游戏顺利发布并引发轰动——事实是,游戏出色的成绩和一言难尽的代码水平构成了鲜明的反差,继而成为其最早的一大记忆点。

如果故事只到这里,那么或许还称得上因祸得福。但EA上架的《太吾绘卷》和上线时已经趋于完成的《小丑牌》处境并不相同,游戏的玩法框架要更自由,茄子本身也还有更多的想法要去实现。
这就导致原本的代码无力承载,茄子则在游戏大获成功后迅速表态希望“把游戏里千疮百孔的代码一一修补起来,为大家带来一个在程序上,更强健、稳定、高效的好玩的游戏”。
后来《太吾绘卷》花了那么大力气去偿还技术债务,大概也是意识到,“差代码”有时能够使得一款好游戏更早顺利发布,但同时,“好代码”能创造更多可能,让一款好游戏变得更好。
2
好的代码能发挥什么作用?
2024年与《小丑牌》有并驾齐驱之势的《动物井》,开发者Billy Basso历时七年,基于C++自行开发游戏引擎。最终,这款画面精致、动态光影复杂的2D像素游戏,安装体积被压缩到极致的33MB。
由于代码高度自研且没有任何冗余的第三方库,Basso能够对游戏的各个方面进行完全的掌控,同时也满足了他构建和理解底层系统的乐趣。
比如游戏中让玩家印象深刻的视觉效果和光照,他表示没有采用单一的着色器,而是使用了约50个小的独立技术,包括动态阴影、边缘光照、水体效果、流体系统等等。
Basso在GDC上的技术分享最终,这种优美的底层代码为游戏的解谜提供了物理层面的深度,也从根本上影响了游戏核心的解谜机制。
玩家或许不会直接审视代码的好坏,但更好的代码确有可能为玩家带来更为优质的游戏体验和更深刻的印象,就像Basso曾表示《动物井》还可以做到更小:“如果我知道人们会如此印象深刻,我可能会更加努力地缩小它”。
也可以说,当游戏的核心玩法乐趣高度依赖代码的复杂功能时,后者的存在感难免愈发明显。
高自由度的《Noita》以技术著称,游戏只设定下物质的基本规则,如水遇火变蒸汽,酸腐蚀木头,剩余的一切交给玩家自行探索,从中诞生出了各种超乎预想的玩法和战术。

其玩法核心的背后是自研的“Falling Sand”引擎:屏幕上的每一颗像素——无论是流动的液体、燃烧的火焰还是被炸碎的岩石——都具备独立的物理属性和化学反应逻辑。
实现这种“像素级物理”需要极高水平的多线程架构和数学建模,相应的,开发团队设计了一套极其稳健的实体组件系统(ECS),使得成千上万个具备物理属性的像素点可以相互碰撞、传导温度、发生相变。
从这个角度看,代码已经不止是实现创意的工具,而是作为创意本身与玩家发生交互。
放在过去,好的代码往往是隐形的。就像一个人身体健康,那么一切都自然而然,只有哪个部位出了毛病,才会清晰感知到其存在。
但随着游戏品类的丰富,开发者与玩家之间的关系拉近,代码时不时也会浮出水面,作为开发者“研发态度”的象征,进而影响到产品的对外形象。
像《戴森球计划》早期做技术分享,就有玩家“恍然大悟”,都是模拟类游戏,为何戴森球十分流畅,隔壁天际线却卡到不行。

包括前面提到的哈迪斯,也是因此收获玩家盛赞,即便玩家可能看不懂代码,但至少读得出诚意。

随之而来的是,伴随着游戏的长线运营,“优美的代码”也成为需要持续维护的对象。
举个例子,好评如潮的模拟工厂流水线游戏《异星工厂》,至今保留着他们的Factorio Friday Facts每周博客文章,目前已更新到400多篇,事无巨细地与玩家分享详细的更新内容、开发见解、新功能和游戏机制,技术细节涵盖从引擎改进到代码效率提升的方方面面。

这下,连代码也成为维系玩家的纽带了。
