第 7 章

纸上的疆域

文件在方瑾的电脑里存了七个月,从预研阶段第一份地图概念草案算起,版本号叠到第十七次的时候,文件名叫“YYSY-MAP-决策终稿-20210514.xlsx”。那是2021年5月14日凌晨两点三十四分,她按下保存,文件名后面加了一个括号,写了三个字——“可交付”。这张Excel表的横轴拉得很长,十六个州名一字排开,像一张被摊平的疆域图。纵轴六列——开发优先级、城池规模、城内建筑密度、野外兴趣点密度、主线任务存在感、支线任务容量。六列乘十六行,九十六个单元格,每个格子里填的不是文字,是数字。优先级从1到4,城池规模从“完整州城”到“界碑仅存”,主线任务容量从0到6。最后一行的总计栏里,方瑾用红色加粗字体标了一行数字:开发城池数——3座;远景预留——4座;仅存其名——9州。

这张表格在A-207会议室的投影仪上亮起来的时候,是晚上七点四十分。窗帘拉了一半,窗外广州五月的晚霞偏橙色,照进来把投影幕布的半边染得有点偏色。

那个文件在七个月的演变中,从最初的“燕云十六州全图构想v1”迭代到“YYSY-MAP-决策终稿-20210514.xlsx”,版本号叠到第十七次。文件名本身就像一部压缩的编年史,记录着从宏大构想向可交付现实的坍缩过程。

沈明远坐在桌子一端,左手边是方瑾,右手边是周成,何铭轩坐在靠窗的位置,保温杯里换了新茶叶。这是第四次会议。前面三次已经把分歧炸开过三轮了。

第一轮炸在州城数量上。那是项目转正后的第六天,历史顾问还没正式进场,周成把一份移动时间表格投到白板上——十六座州城按《武经总要》记载的驿站间距换算成游戏内骑乘时间,幽州到顺州需要大约七十三分钟,幽州到云州东西横穿全线不吃不喝不停马,六个多小时。何铭轩当时把保温杯往桌上一顿,说了一句“玩家从一座城骑马到隔壁那座城,要在屏幕上按着W键看着同一片地貌一个小时零十三分钟”。会议室安静的时间长度,沈明远后来跟方瑾说起过——足足七秒。

那天没人能反驳何铭轩。因为数字本身就在反驳所有人。谭其骧《中国历史地图集》第六册辽宋时期那一页的复印件,被放大到A0尺寸铺在会议桌上,州治所在的位置标着小圆圈,旁边注着宋体字,州与州之间有虚线连缀。谭其骧不需要考虑玩家的马跑多快。但周成需要。

他在那次会上调出了另一张表,列着“城池间距”“途中兴趣点数量”“兴趣点制作工时”。野外兴趣点——一处废弃驿站、一个山贼营地、一座路边茶寮——单人全流程十五到二十个工作日。十六座州城,按最低标准在两城之间布置兴趣点,野外点位总数超过二百个,仅场景建模和关卡脚本一项,需要的工作日总数超过一万二千天。

方瑾当场算了账——场景组加关卡组一共十九个人,一年有效工作日二百二十天,年产出四千一百八十个人日,一万二千天需要将近三年,“而且只做地图,不做战斗、不做任务、不做剧情、不做音效、不做UI”。所以她在那次会上写下的笔记,后来被拍照发进项目群里的那一页,上面有一行字:“如果我们在游戏里放十六座城,玩家会用脚投票——他们根本到不了其中十三座。”

第二轮炸在历史顾问进场之后。浙江大学历史系的陈望安副教授、北京大学考古文博学院的陆鸣谦副研究员,两个人隔着视频画面,一个在杭州的书房里,一个在北京的书房里,背景里都摞着书。陈望安先开了口,语气带着学院派的审慎,但措辞不轻——“如果你们一开始就把十六州压缩成三个州,玩家接收到的信息就是燕云十六州不过如此,就是三座城加一些野地,这会对他们形成错误的历史认知。”

沈明远在那次会上没有直接回应,而是把周成提前准备的设计需求表放到摄像头前。玩家在开放世界前三十分钟的遭遇密度要求、视觉疲劳度曲线、移动端帧率底线,每一项都对应着量化指标。他说了一句后来被方瑾记录在会议纪要里的话:“如果我们做出来的游戏根本没人玩,那历史再准确也到达不了任何玩家。”

陆鸣谦接了话柄,他抛出的问题正好打中沈明远在立项评审会上对陈言说过的那个词——“可感知的真实”。如果地图本身背叛了真实,可感知的真实就丧失了地基。那次会的后半程,方瑾在笔记本上画了一个三角形,三个顶点标着“历史准确度”“游戏可玩性”“开发可行性”,中间写了一个词——“可交付的疆域”。她把这页笔记推到摄像头前,说了一段话:“我们现在面对的不是三个抽象概念在打架,我们面对的是五十个人的命。如果十二个月里拿不出一个可以让人玩半小时的版本,下一个季度复审这个项目就会被砍掉。到时候不要说三座城,半座城也做不出来。”

陈望安松了口,但底线没退——城池本身的建筑格局,城墙规制、城门方位、坊巷结构,必须按宋代州城制度来做。五代末到宋初的州城,城墙周长一般在八里到十五里之间,城门四方各一,城内十字街或丁字街分割坊区,衙署位于城北偏西。“这些基本骨架不能变。如果你们连这个都改了,我们顾问身份就没有意义了。”

周成当时在iPad上打开了一张草图,按《武经总要》规制画的,四门十字主街衙署西北。陈望安看了点了头,但紧接着抛出第二个要求——三座城必须承载十六州的地理多样性。幽州北境重镇城墙高厚驻军众多,云州草原与农耕交汇带马市皮毛交易密集,蔚州太行山西侧地势高峻城内多山坡水井深达二十丈。“三座城,不能是三座长得差不多的城。”

这句话压下来的工作量,何铭轩在心里算过——三座城三套完整建筑风貌和城市生态,美术资产无法复用,每座城都得单独建模。比做一座城复制三次的工作量大得多。但这个要求在游戏设计逻辑上也立得住——玩家为什么要从幽州走到云州再走到蔚州?不就是因为每座城长得不一样玩起来不一样吗?沈明远在那个节点上提出了第一个关键妥协方案——界碑方案。那些做不了的城,不消灭它们,把它们变成传闻。玩家走到地图边缘,会看到一块半人高的石牌,阴刻州名,两侧灌木和山石,再往前就是暂未开放的迷雾区域。商人会提到蓟州的马市,逃兵会说起涿州的沙场,茶馆里的说书人会讲瀛州水战的故事。

“可见与可入”的层次划分,成为整个项目后来处理历史考据与游戏压缩之间关系的基本方法论。陈望安和陆鸣谦几乎同时点了头。陆鸣谦补了一句:“宋代的州与州之间本来就有明确的分界标识,石牌坊、界碑、垭口,文献里都有记载。你们用界碑来做地图边界,反而符合历史真实。”

第三轮就炸得比较难看了。炸在幽州城墙的雉堞上。何铭轩花了三天时间做了幽州城墙初步模型,截了图发项目组内部群,备注写的是“城墙面数超了,渲染压力大,得砍。”陆鸣谦在群里回了一张辽南京城考古平面图,圈出雉堞位置,回复只有一句话——“雉堞不能砍。这是宋代城墙最基本的防卫结构,砍了等于告诉所有懂历史的人,这座城是假的。”

何铭轩约了陆鸣谦单聊,开了录屏。录屏记录后来方瑾拿到了,会议纪要里引了原话。何铭轩把幽州城墙的模型打开,逐层拆解面数。城墙主体、瓮城、雉堞、角楼、护城河驳岸,每一层都标着多边形计数。总面数超过一百二十万三角面,仅雉堞一项——城墙上重复排列的垛口和射孔——就占了将近三十万面。他对着屏幕那边说:“不是我要砍,是我们的渲染管线扛不住。引擎要实时加载整座幽州城,四面城墙加上城内建筑再加上城外地形,场景总面数必须控制在三百万面以内,否则移动端加载时爆内存,低端机直接闪退。”

他在屏幕上标出红线,“三百万面的总预算里,城墙只能吃掉四十万面。您要雉堞,我就得砍角楼。您要角楼,我就得压缩瓮城。您要护城河的水面反射,我就得把远处的城墙用面片代替。”

陆鸣谦沉默了。他的专业训练让他无法接受一座没有雉堞的宋代城墙,但何铭轩报出的数字也让他意识到这不是审美问题,是物理问题。他问了一句——“四十万面是什么概念?”

何铭轩切到对比画面。四十万面的城墙模型和三十万面的雉堞拆解开,并排显示。“这是雉堞,三十万面。这是剩下的城墙本体,只有十万面。十万面做一圈城墙,面数分配到每一段上,贴图精度不够,砖缝都会被拉伸糊掉。”他把雉堞模型放大,“雉堞的每一齿都是独立模型,齿间距必须均匀,否则从侧面看会变形。每段城墙长度不同,雉堞数量不同,没法用同一个预制件复制粘贴。每一段都单独建模,单独排布,面数没法分摊。”

陆鸣谦在考古现场见过真实宋代的雉堞遗址。垛口高约五尺宽约三尺齿间距大约四尺,每一组雉堞就是一个射击位兼掩体,城墙最基本的战术单元。没了它,城墙就只是一道高台。但他也知道何铭轩不是在跟他谈历史,是在谈显卡。“有没有中间方案?”

何铭轩调出第三张图。他测试了三种备选方案。第一种全建模雉堞,面数三十万,直接毙掉。第二种法线贴图替代,雉堞不做真实几何体只在城墙顶部平面用法线贴图伪造凹凸效果,面数控制在五万以内,但缺陷明显——玩家骑马从城墙下方经过时视点角度一低凹凸贴图立刻穿帮,雉堞看起来像是贴在城墙上的纸片。

第三种是混合方案。城门两侧各一段城墙保留全建模雉堞,长度约为城墙总长的四分之一。其余四分之三用简化雉堞——减少齿数增大齿间距,整体面数压缩到原来一半,但保留雉堞的剪影轮廓。整圈城墙的雉堞面数从三十万降到十二万,加上城墙本体十万面,总面数控制在二十二万,在四十万预算里还有余量。“城门两侧的雉堞保留原始精度,玩家最可能近距离经过和截图的位置就是城门洞。那里的雉堞如果是假的,贴吧和论坛会炸。远处的城墙雉堞拉大间距,玩家骑马经过时余光能看到剪影,形是对的,但不会有人在城墙底下抬头数齿数。”

录屏记录里,陆鸣谦盯着那三张对比图看了将近两分钟。这段时间里只有鼠标移动的声音。“混合方案我可以接受。”他终于开口。“但有一个条件:简化雉堞的齿间距不能超过八尺。宋代实测雉堞间距在四尺到六尺之间,八尺已经是极限值的两倍了。再拉开,剪影轮廓就会从雉堞变成一段一段的矮墙。”

何铭轩快速算了一下。齿间距从四尺拉大到八尺,单位长度内雉堞数量减少一半,面数相应减少一半,还能承受。他在备注里记下:简化雉堞齿间距≤8尺,齿高≥4尺,保留剪影辨识度。这个方案后来被何铭轩自己评价为“在正确和能跑之间劈开的一条细缝”——幽州城墙上的雉堞有三分之一是真的,三分之二是假的。站在城门洞里抬头看,雉堞是宋代的;骑马从远处跑过去,雉堞的轮廓也像那么回事;但如果真的停下来对准那段简化的城墙仔细看,会觉得这里的雉堞好像有点稀疏。

这三轮冲突炸完之后,沈明远让方瑾做了那张最终决策表。第四次会议的开头,方瑾把Excel表投到幕布上,从第一行幽州开始过。幽州——优先级1,城池规模“完整州城”,城内建筑密度“宋代城市街区水平”,主线任务容量6。备注栏里写着何铭轩的注记:城墙用混合雉堞方案,总面数控制22万;城门两侧雉堞保留原始精度,远处齿间距≤8尺;主街宽度15米,檐口高度5-6米,高宽比1:2.5。

蔚州——优先级1,城池规模“完整州城”,但备注栏的标注完全不一样:山城地势特殊,城内建筑依山就势悬空建造,不需要完整城墙围合,雉堞仅在城防段出现,面数压力比幽州小得多。城内水井深度按陈望安批注修正为二十丈,不是十五丈。云州——优先级1,城池规模“完整州城”。备注栏:南城墙面对草原做夯土本色,北城墙面对农耕区包砖,马市位置按陈望安批注从城南移到城西。

绿色区域划完,三座城。方瑾把表格往下翻,切到黄色区域。朔州、蓟州、妫州、武州——优先级3,城池规模“远景预留”,野外兴趣点密度0,主线任务容量0。备注栏统一写着“界碑方案”——在世界地图上保留城址和地形基础,远景用低模呈现城墙轮廓和塔楼剪影,玩家到不了城下,只能在地图上找到一个标记。

再往下翻是红色区域。涿、檀、顺、新、儒、应、寰、瀛、莫九州——优先级4,城池规模“仅存其名”,所有维度都是0。备注栏:名字出现在NPC对话、道具文字描述、背景故事信件和碑刻中,不占据任何开发资源。这张表翻完之后,沈明远拿起一支红笔,在幽州、蔚州、云州上画了圈。“这就是我们的燕云。”

他说这句话的时候,投影幕布上的Excel表被方瑾切到了总计行。她用红色加粗字体标了两行数字——开发城池3座,远景预留4座,仅存其名9州。下面一行写的是总面积:约二十平方公里。她在这行数字旁边用括号注了一行小字——谭其骧地图集燕云十六州覆盖地理面积约十二万平方公里,本方案约二十平方公里,比例约1:6000。周一成在自己面前放着的那张打印版决策表上,用笔勾出了和叙事线相关的六个数字。

方瑾在第三次会议和周成之间爆发过一场争执,争执的内容不在何铭轩和陈望安的战线之间,而在游戏设计内部的两套逻辑之间。周成的习惯节奏是每八百米一个据点,两公里一座具备传送功能的城镇,这套节奏在《逆水寒》野外地图上跑通验证过。但方瑾拿出了一条横跨三州的主线故事——主角从幽州边关军营出发,沿桑干河谷地向西走,穿过太行山隘口进入蔚州山地,最终在云州草原前线完成核心剧情——这条主线需要经过六个关键叙事节点。边关要塞、战场遗址、流民营地、山间寺庙、草原马市、边境军镇。

“这六个节点缺一个,叙事线就断了。”方瑾那时把叙事节点的位置标注在周成的兴趣点分布图上,标注的间距远远超过八百米据点间隔原则。边关要塞到战场遗址,她需要至少四到五公里的距离,“玩家从有序的军营过渡到混乱的焦土,这个情绪转变需要空间距离来承载”。周成当场算了空窗期——四到五公里的空白距离,玩家会经历将近四个空窗触发点。

两个人的分歧在会议室里僵了将近二十分钟,没有像雉堞之争那样在陆鸣谦的一句“八尺”上达成妥协。沈明远那天的解决方案不带任何美学判断,只带了一个测绘数字。他让周成调出地图方案,精确测绘了方瑾的六个叙事节点按顺序连起来的路径总长度——将近四十公里。他盯着那个数字看了很久,说了一句话——“砍”。

但他砍的不是叙事节点之间的间距,而是减少叙事节点数量。流民营地和草原马市被砍掉,叙事功能合并到战场遗址和边境军镇里。边关要塞到战场遗址的距离保持不变,四公里以上。战场遗址到山间寺庙三公里以上。总路程从四十公里压到十六公里。

他在那次会上对方瑾说:“节点间距不压缩。玩家分三段走,每段三到四公里,加上停留时间,可以控制在移动疲劳阈值之内。叙事线的情绪累积还在,叙事节点的数量少了。”

方瑾当时在笔记本上记了一行字:“流民营地→合并入战场遗址;草原马市→合并入边境军镇。”合上笔记的时候说了一句——“我们砍掉的不只是两个任务点,是五代十国历史上这一带真实存在过的两种人群。流民营和边贸马市,就是燕云地区最典型的人口流动形态。我们在叙事线里消灭了它们。”

那天的会议室没人接这句话。沉默不是否定,是所有人心里都清楚——方瑾说得对,但如果他们不先消灭掉这些,整个项目就会被消灭掉。

现在,在第四次会议上,方瑾把修改后的叙事节点表投到幕布上。六个节点变成了四个,路径总长十六公里。周成在旁边把兴趣点分布表叠上去,之前空出的八公里空白区间已经按八百米间隔重新插入了野外遭遇点和采集点,分布在主线道路两侧,不需要玩家偏离路线很远。沈明远在那张最终决策表的幽州一行主线任务容量栏里,填上了6。这个数字不是方瑾定的,是沈明远自己填的。

他在立项评审会上对陈言承诺过——单人体验版本的核心叙事密度必须保证。6个主线任务节点,刚好够一条完整的叙事弧在三个城市之间拉开,也刚好在这个项目的性能预算和开发工期内可以活下来。何铭轩在那个晚上走出A-207的时候,对着走廊尽头窗户外的夜色说了一句话。他说:“这张地图只要一上线,一定会有人说我们缩水了燕云。”

周成走在他旁边,回了一句:“让他们说。总比他们根本没机会看到强。”

在方瑾把Excel表翻到红色区域之前,会议室里有一段将近三分钟的沉默。不是没人说话,是所有人都在看同一组数字——何铭轩在第三次会议结束后连夜跑出来的性能预算表。他把二十平方公里的地图按地形类型切成七个区块,每个区块标了面数上限、贴图内存上限、同屏物件数量上限。

幽州城区块的面数上限是三百万面,云州草原区块因为植被密度高,面数上限压到了一百八十万面,蔚州山地区块因为地形起伏大、遮挡剔除效率高,反而能放宽到二百二十万面。七个区块加起来,总面数预算一千四百六十万面。何铭轩在这行数字下面用红字写了一行备注:“移动端中配机型(骁龙870/天玑1200)稳定30帧的前提下,场景总面数不得超过1500万面。超过此阈值,低端机(骁龙732G/天玑800)帧率将跌破24帧,触发应用商店审核红线。”

这张表投在幕布上的时候,周成正在翻他自己的移动端性能测试记录。他在预研阶段拿三款不同配置的测试机跑过开放世界场景demo,低端机上跑到二十三帧的时候,画面开始出现明显的撕裂和延迟加载——地面贴图先是一片模糊,然后突然跳成清晰版本,远处的建筑从低模瞬间切换成高模,整个过程在屏幕上看起来像是一块一块地拼上去的。

他把测试机的录屏投到投影仪上,画面里玩家骑马穿过一片平原,前方的城池轮廓在视野尽头若隐若现,但城池的细节——城墙的砖缝、城楼的瓦片、城门洞的阴影——是在马跑到距离城墙大约三百米的时候才突然加载出来的。周成按下暂停,用激光笔圈出那个加载瞬间。

“这就是面数超限的代价。LOD(细节层次)切换距离被强制拉近,玩家能看到城池在眼前‘长出来’。一次两次可以,十次二十次,沉浸感就碎了。”

何铭轩接过了激光笔,把画面切回性能预算表。他的手指沿着幽州城区块的三百万面预算往下滑,滑到城墙的二十二万面,滑到城内主要建筑的八十五万面,滑到街巷和地面的四十三万面,滑到NPC模型的十二万面。每一项都是硬的,每一项都是从别的地方切过来的。他在城墙那一行旁边用红笔写了一个数字——22万/300万,占比7.3%。然后他在雉堞那一行又写了一个数字——12万/22万,占比54.5%。

“一座幽州城,城墙只占场景总面数的百分之七点三,但雉堞吃掉了城墙面数的一半以上。”他把笔放下,看着陈望安的摄像头画面,“陈老师,我给您交个底。

幽州城墙上的雉堞,混合方案里的那四分之一真雉堞,面数是八万面。剩下四分之三的简化雉堞,面数是四万面。如果按您最开始的要求,全城墙保留原始精度的雉堞,面数是三十万面。这三十万面从哪里来?从城内建筑来。幽州城里的坊巷、店铺、衙署、寺庙,总共八十五万面。我砍掉二十二万面给雉堞,城内建筑就只剩六十三万面。六十三万面做一座宋代州城的全部建筑,您知道这意味着什么吗?”

陈望安没有回答。何铭轩自己回答了。“意味着城内建筑密度要砍掉四分之一。意味着坊巷格局会出现空缺。意味着玩家走进幽州城,看到的是一个被抽掉了几十栋房子的、稀疏的宋代城市。那不是历史还原,那是历史残骸。”

这句话落下去的时候,陆鸣谦在视频画面里摘下了眼镜,用眼镜布慢慢擦着镜片。他的声音比之前低了一些。“何老师,你说的这个——‘历史残骸’——恰恰是我们最怕的东西。我们怕的不是你们砍掉几座城。我们怕的是留下来的城,看起来像是被轰炸过的。”

沈明远在这个节点上插了一句话。他没有对着任何人说,而是对着幕布上的性能预算表说的。“我们不是在做考古复原。我们是在做一个玩家能在手机上跑起来的游戏。如果一座城的面数预算只能支撑‘完整’或‘残骸’二选一,我选完整——哪怕完整的代价是城墙上的雉堞有一部分是假的。”

陆鸣谦把眼镜戴回去,说了一句后来被方瑾记录在会议纪要里的话:“我理解了。但我必须声明:幽州城墙的混合雉堞方案,从考古学角度看是不合格的。我只是在‘不合格’和‘更不合格’之间选了前者。”

方瑾在那张Excel表的幽州备注栏里加了一行字:“陆鸣谦声明:混合雉堞方案考古学不合格,属被迫接受。”她敲完这行字的时候,抬头看了一眼沈明远。沈明远没有看她,他在看周成刚刚推过来的一张新表——移动端加载距离与面数分配的关系曲线。那条曲线在面数超过一千四百万面之后开始陡峭下跌,跌到一千五百万面时触底,触底的位置标着一行字:“低端机帧率≤24fps,触发发行审核红线。”沈明远用红笔在那条红线上画了一个圈,然后把笔搁下。“这条线就是我们所有争论的终点。不是历史,不是设计,不是叙事。是这条线。”

云州的争议比幽州来得晚,但炸得更碎。

走廊的声控灯在他们走过去之后灭了。A-207的最后一点光来自会议室里那盏还在运行状态的投影仪。投影仪打在幕布上的,是那张幽州城墙的混合雉堞方案图——城门两侧的雉堞密集排列,延伸到远处时逐渐变稀。从投影的角度看过去,那条锯齿状的城墙剪影像一个被拉长了的妥协的符号。

沈明远在凌晨离开办公室前,把那支红笔放回笔筒,把茶杯从地图上拿开。谭其骧那页复印件还铺在会议桌上,四个角被他用几只马克杯压了将近四个小时之后,地图纸的纤维里留下了一圈茶渍的印子。他把地图卷起来,幽州被裹进了纸卷的内层,云州折在中间,蔚州压在最外圈。放进会议桌下面的抽屉时,他在黑暗里对何铭轩说:“明天开始,把这张图上的东西搬进引擎。引擎里的沙盘才是真的沙盘。”

抽屉关上了。那张Excel表留在方瑾的电脑里,文件名末尾挂着三个字——可交付。这个文件在项目工程文档里存了很长时间,后来的每一次版本迭代都会引用它作为基准线。但那个二十平方公里的总面积数字,从2021年5月14日凌晨两点三十四分起,就没有再动过。不是因为那是最优解,而是因为那是当时能交付的唯一解。