作者:叶兰舟 公众号“叶师傅说游戏”
实际上如果你做过游戏就会发现,那些超巨大的项目,到最后真的能顺利运行,本身简直就已经是一种工程奇迹了……
我随便举个例子。如果你在一个动作游戏中受到一次攻击,会牵扯到哪些系统呢?
伤害计算系统往往是第一个入场的,它需要根据公式,计算是否命中,中了再算护甲,减伤,暴击,格挡和各种 BUFF/DEBUFF ,然后把数据发给全局管理器。
接下去,管理器就会根据具体的数据,开始一个个调度对应的系统。
UI 系统会被叫起来。如果打中了,那血条跟生命数字得变吧?头顶上要跳伤害数字吧?屏幕边角可能也要闪个红光什么的?即使没打中,也得跳个 MISS 。
音频系统跟动画系统则要立即播放受击的音效,受击的动画和特效,它往往还会连着摄像机系统,来点震屏活跃气氛。
如果伤害产生了击退/击飞效果,物理系统也要介入检查,这多半后面还连着一大堆东西,咱们先别管。
很多游戏里都有相关受伤的成就,那么成就系统也得检查,是否达成了「受到 1000 点伤害」之类的东西,对应的记录系统这时候也在疯狂记录,等回头要告诉你在游戏中总共受到了多少点伤害,死了多少次。
要是有跟血量变化有关的被动技能,技能系统也会被叫起来工作,说不定还得踹一脚旁边的装备系统,让它一起干活——通常来说装备技能跟人物技能的格式和系统都是一样的,只是写得不一样。
要是你不幸嗝屁,死亡、加载跟重开等系统也会被唤醒,这就又是一大片关联功能被触发了。
最后,如果是联机游戏,这前面的很多数据还都得同步给其他玩家,联网模块又要疯狂干活。
这中间只要有一行代码出问题,就会出现各种千奇百怪的问题,轻则显示的数据不正常,重则角色以光速飞出地图,或者掉进地面下面的虚空,又或者干脆直接闪退、死机。
当然,现代的游戏架构也在不断改进,把各个模块尽可能独立化,使得某个模块出的问题只影响其本身,但理想很丰满,现实很骨感啊!
比如巫师 3 的 DLC 「血与酒」里,有个围攻城堡的任务,为了让玩家跟着剧情走,不能让玩家随便在其他建筑里乱跑,所以任务开始前,需要用脚本把所有的门锁上,弄完再开,听起来好像还挺安全的对吧?

就是这个城堡Dun Tynne Castle
结果程序写的时候,没有记录「哪些门是这个任务相关的」,所以任务完成的时候,就直接把「所有的门」统统都开了——好家伙,这还包括那些原本只是装饰,里面根本没有地面的房子呢,走进去就会掉进虚空,结果团队只好把游戏里的几千扇门都检查一遍,标记哪些门是绝对不能开的。
还有 2004 年的 GTA :圣安地列斯也是,程序员把一个叫 Skimmer 的载具,从船只改成了飞机,却忘了补上关于轮子尺寸的三个参数,结果这玩意儿居然安安稳稳地跑起来了,完全没人发现。为啥?因为当时的 windows 版本中,游戏的内存里会有上一辆载具的轮子数据,程序刚好把它偷来用,于是它居然也就这样一直运行下去了。
直到 20 多年后的 2025 年, Windows 11 的一次系统更新重写了内存机制,导致运行在新系统上的游戏读不到那个数据,这个飞机就生成不出来了。有玩家强行生成它,于是是连人带飞机被发射到了 1.087 千万亿光年外的高空——你没看错,写出来就是 1087000000000000 光年——结果还能怎样?游戏当场死给你看呗。
我查了查,还有个例子也挺有趣的,就是一个叫「浣熊推币机」的独立游戏,他们加了一枚能把周围硬币全粘在一起的「胶胶币」,听起来挺有趣的吧?
结果是全员差点给整崩溃了。因为他们之前就做了百多种硬币,然后这个胶胶币跟一种硬币黏在一起是一种情况,跟另一种黏在一起又是另一种情况,这可就复杂了……
比如有的狼币会跳起来捕食别的币,那如果它被胶住了,是带着一坨东西一起飞,还是挣脱出去?有的炸弹币会爆炸,那如果它被胶住了,是炸飞所有粘在一起的币,还是只炸自己?
这解决起来都是巨烦的问题……
看到这里,你也许会问:那么有没有可能,一开始就把代码写得干干净净、把每个系统都完全隔离开?
能,也不能。
首先,现代的游戏很少是全写完策划案才开工的,大型游戏更是一边做一边改,甚至做到中途大改特改,太正常了。今天策划加个新点子,可能就把之前的很多设计统统推翻了;在这种情况下,代码想要完全干净,做梦呢。
其次,很多游戏的设计,本身就非常依赖于这些系统的耦合。我们可以把游戏的内容用 2 个象限进行划分,也就是玩法来源跟可控程度。

左上角就是系统规则+部分可控,会有多结局、不同选择导致的支线结果等。
右上角就是叙事来源+完全可控,游戏的叙事过程完全是线性的,比如 COD 。
左下角则是可控程度来源于规则,比如 Minecraft 就是最典型的例子,谁都不知道玩家能用里面的东西捣鼓出什么鬼玩意儿。
右下角则是系统提供规则,但结局可控,深度可预估。
对于右上角这些可控程度较高的游戏来说,确实程序模块上可以做得较为清晰、明确,不容易牵一发而动全身;但对于左下的,那就真的很难讲了。
所以对于开发者来说,开头最麻烦的,就是建立好一个良好而强壮的架构,而到了中间和后面,就只能期待别有什么大改的需求了……