《黑神话:悟空》游戏体积高达 139G,而它的存档文件只有 2.66MB。然而这个小小的文件却能存下你的整个游戏世界。

这种现象发生在各种游戏中:千军万马的战场、玩家手搓的自建房、甚至整个星球和宇宙,都能被瞬间保留下来。那么游戏存档的时候到底发生了什么?

黑神话悟空存档读取界面

你以为的存档,其实是制作者的障眼法

玩了几十年游戏,存档和读档已经成为习惯性动作。按下存储,一瞬间记下所有进度,关机断电,一两年后再读档,那个世界又精确地停留在你按下存档的那一刻。

但仔细想想,这其实挺神奇的。时隔很久回到《无人深空》,游戏不但记得所有物品、枪械和飞船改造,你去到一个自己都不记得什么时候建的基地,里面所有改动也都被保存了。星球是完全随机生成的,它不仅记得你探索过的星系,还记得星球上的地貌、基地的设施、甚至储物箱里放的东西。

多数玩家在潜意识里脑补了一个幻想:游戏存档是把整个世界,大到地图小到每一粒灰尘,都记录在案,读档时再神奇地还原回来。

然而实际上,绝大多数游戏存档都是选择性的。它只会保留一些关键数据:玩家所在的关卡、位置、生命值、装备、背包道具。因为玩家就是通过这些来判断游戏进度的,这些信息保存下来,玩家就会产生整个世界都被保存的错觉。

早期存档:玩家当人肉硬盘

早期家用游戏机把存档存在软盘和磁带上,普遍只有几十甚至上百 KB,装下一个游戏都吃力,留给存档的空间更有限。磁带不但容量小,读取还特别慢,读个档需要好几分钟。

所以制作者必须把存档做得尽量紧凑,只记录最重要的数据。有些主机卡带是只读的,根本不能写入,逼出了更另类的方法。

1983 年雅达利游戏《生存岛》,因为内容太大内存装不下,制作者把游戏分成三个章节,第一章结束后清空内存加载第二章。但系统不支持写入存档,玩家状态和物品也会被清除。于是他们设计了一套密码系统:第一章结尾,游戏把所有需要保存的数据转化成一串 12 个字符的代码,玩家用笔记下来,第二章开始时再输入回去。玩家相当于外置的人肉硬盘。厉害的存档代码口口相传之后,就变成了游戏秘籍。

银河战士Famicom磁盘系统存档界面

1986 年初代《银河战士》,日版有正常存档功能,但欧美版因硬件限制依然用代码存档。银河战士是类银河恶魔城游戏,世界复杂,需要记录主角获得了哪些能力、哪个门被打开、哪些 Boss 被击败。12 位数字代码不够用了,制作组把代码扩张到 24 位,加入大小写英文字母和符号,共 64 种字符。这样的代码可以存储 144 比特数据,其中 8 比特是加密算法,8 比特是数据校验,剩下 128 比特记录游戏信息——几乎是一个比特对应游戏中的一个东西。

到了 NES 版《塞尔达传说》,需要记录的信息更多,估算约 187 字节,用代码系统至少需要 250 个字符。所以它不再用代码存档,而是在卡带中内置了一颗 SRAM 芯片,还自带纽扣电池供电。

现代游戏为什么还是不能存整个世界

现在硬盘可以轻松装下几百部电影,但把整个游戏世界直接存到硬盘上仍然不可行。

一个重要原因是现代游戏的数据结构复杂了太多。比如开一枪,为了计算经验值需要知道是谁开的枪;子弹为了计算弹道需要知道从哪支枪打出来;命中后为了计算伤害需要知道打中了谁。事物之间形成一张复杂的关系网,计算机科学中叫指针和引用。任何一根线断了,游戏可能当场报错或卡死。

而内存可以想象成有无数房间的仓库。游戏启动时,各种对象被临时安排到各个房间。你在河边扔了一把剑,游戏给它分配 302 号房。但这个房间号只在本次运行中有效。关闭游戏仓库被清空,下次运行所有对象重新分配房间,这把剑可能就到 501 了。如果存档只是把内存内容原封不动记下来,写着剑在 302 号房,再去 302 找——这就是赛博版的刻舟求剑。

所以多数现代游戏不能把内存数据直接存到硬盘。常见的做法是:不记录剑在内存的什么地方,而是记录它的关键属性——这是一把铁剑,耐久度剩 37,位置在河流区域的什么坐标,剑尖朝东。然后把这些数据转化成适合写入硬盘的格式,这个过程叫序列化。读档时进行反序列化,根据这些信息在游戏里重新生成一把剑。玩家看到一把一样的剑以相同状态待在相同地方,自然觉得世界还是之前的世界。

空中飘着多少片树叶、它们朝向哪里、以什么速度旋转——这类数据通常不需要保存。下次进入游戏重新生成一些树叶让它们继续飘就行,玩家根本不会在意这片叶子是不是上次那片。

设计存档系统:到底需要记住什么

设计一套存档系统,本质上就是在思考一个问题:为了重构一个看起来一样的世界,我们究竟需要记住什么?

存档逻辑通常是:存档时向所有有接口的对象发出指令,让它们提交自己的数据。玩家角色记录位置、金币、生命值;敌人记录当前血量和位置。但有些物体有特殊功能,需要专门设计存档逻辑。

比如一个一次性开关,玩家第一次交互后就变成被踩下去的状态。如果不记录,存档再读档它又弹回来了。所以需要在存档里添加一个变量,记录每个开关的 UID 和是否被交互过。读档时,每个开关检查自己"上一辈子的记忆",如果被交互过就恢复按下状态。

金币的坑:需要一本"生死簿"

开关的逻辑搞定了,金币看起来也差不多——被玩家触碰后原地销毁,记录是否交互过,读档时检查销毁就行。但实际用下来不对:金币还在。

原因很有意思:金币被销毁后就从游戏世界里消失了,存档时召唤所有存在的对象提交数据,这枚金币已经没了,它无法把自己的状态提交给系统。所以读档时它不知道自己"已经死过",又回到了初始状态。

解决方案是准备一本生死簿,专门记录所有和玩家交互过的一次性道具。每个金币在销毁前增加一个动作:到系统里报备,把自己的名字写在生死簿上。存档时直接把生死簿存下来。读档时每个金币生成后先到生死簿上查一下有没有自己的名字,有就直接自刎归天。

不同游戏,不同的存档策略

存档规则会直接影响游戏玩法和体验,所以每个被记住的属性都需要制作者手动设定。从人工成本上说,游戏也不可能保存所有数据。

《明日方舟》的迷质会自己跑,它有交互信息还有位置信息,但游戏实际上不保存它的位置。如果你在追迷质的过程中退出游戏,再回来时迷质不会待在你离开的地方,而是回到初始位置——这是制作者有意设计的。每个迷质是一个小小的解谜挑战,被吃掉说明挑战成功,没被吃掉就退出说明放弃了挑战,下次回来重置挑战。

《赛博朋克 2077》中街边的垃圾、小道具状态通常不会被记录,你把它们踢走或破坏后再读档,它们又会在默认位置重生。一方面玩家一般不会注意这些细枝末节,另一方面即使注意到了也不影响核心体验。

"丢档英雄":把存档机制做成游戏

为了让大家直观理解存档过程,UP 主用 AI 做了一个演示用的小游戏叫《丢档英雄》。表面上是普通的地牢探索肉鸽游戏,战斗自动进行,胜利后获得技能道具增强战斗力。但它的特点是:存档规则不是预先设定的,而是需要玩家手动选择把哪些数据存到存档里。

每三个回合,主角会遭遇不可抗力被强制销毁,但死前可以进行一次存档。此时游戏中所有数据散落在地块上:生命值、攻击力、道具、技能、金币、装备。玩家可以把数据捡起来存到硬盘中,但主角硬盘空间有限,每次只能走有限步数,超过步数的数据就记不住了。

存档完成后主角立刻原地读档重生。如果之前提升了攻击力但存档时没保存,读档时攻击力就会被重置;不存金币,之前捡的金币归零;但如果存档时没有存储生命值,进入游戏后会发现生命值神奇地被补满了——因为生命值的默认值就是生命上限,没有被保存的数据读档时恢复为默认值。所以在《丢档英雄》里,生命值在存档阶段其实是一个 Debuff,玩家可以主动不存它来实现回血。

结语

所以回到开头的问题:游戏存档到底是如何把整个游戏世界保存下来的?

答案是它根本没有尝试这么做。

游戏里并没有什么神奇功能能一瞬间记住整个世界的所有信息。存档里保存的不是世界本身,而是重构这个世界所需要的最基本数据。在这个过程中,大部分信息其实都被抛弃了。等你读档的时候,回到的世界并不是你离开的世界,而是一个新造的世界。

旧的世界怎么办?很遗憾,你在退出游戏的那一刻,那个世界就已经被销毁了。《无敌破坏王》里游戏角色在玩家离开后依然可以在游戏中生活,也只是一种美好的想象而已。


资料来源:B 站视频 BV1puH46qE3o(UP 主"失业",游戏存档系统原理深度拆解)。配图:《黑神话:悟空》存档界面、《银河战士》Famicom 磁盘系统存档界面。