内测开放第三天,后台监控面板上的长安城地图区域亮成了一片白色。
那片白色不是正常的浅灰底色,是角色密度超过阈值之后系统自动标注的红色警告叠了一层又一层,把整片主城区的网格染成了刺眼的亮斑。
梁永琪站在监控大屏前面,屏幕上长安大街的俯视图里挤着上千个蓝色的光点,每个光点代表一个在线角色,光点之间已经没有了空隙,全部挤成了几团密度过高的光团。
那些光团还在不断膨胀,边缘不断有新的蓝色光点汇入,像一滴墨掉进清水里,越晕越大,越晕越浓。
技术组的测试员在旁边的工位上跑了一轮实机测试。
他的角色从长安大街的东侧入口进去,刚走了三步,画面就开始顿。
帧数从三十帧掉到十五帧,再掉到个位数,屏幕上角色的移动变成了跳帧式的推进,走一步停两秒,再走一步又停两秒。
他按了一下方向键让角色往路边靠,角色瞬移了两米,像被什么东西从后面推了一把。
测试员又按了一下反方向键,角色没有反应,过了三秒之后突然往反方向弹了五六米,直接卡进了路边一个摆摊NPC的模型里面,半个身子嵌在摊位桌板中间,只露出上半身在外面,两只手还在空中做着奔跑的摆动动作。
“瞬移出现了。”测试员说了一句,手指在键盘上敲了两下,把帧数日志导了出来。
他又补了一句,“比昨天严重多了,昨天只是偶尔跳一下,今天基本走不动。”
李轩从机房那边走过来,站在测试员身后看着屏幕上的角色在原地跳帧。
他的眉头皱着,两只手插在口袋里,手指在裤袋里微微动着,像在脑子里跑代码。
他站了大约两分钟,眼睛一直盯着屏幕上那个卡在摊位里的角色,看着它每隔几秒就往不同方向弹一下,每次弹的位置都不一样,有时候往左,有时候往右,有时候直接弹到半空中又落下来。
然后他转身走回机房,打开了自己的主控机。
梁永琪跟在后面走进了机房。
李轩坐在主控机前面,屏幕上已经打开了渲染引擎的参数配置表。
他的手指在键盘上快速翻页,翻到同屏渲染上限那一栏的时候停了下来。
那一栏的数值设的是八百。
他把光标停在那个数字上面,没有改。
屏幕上的参数表密密麻麻排了几十行,每一行都是一个可能影响性能的变量,但李轩的眼睛只盯着那个八百。
“引擎的同屏渲染上限是八百个角色。”他说,声音不高,语速比平时慢一些,像在一边想一边说,“长安大街同时挤进来一千两百多个人,超过上限的那部分角色全部被引擎丢掉了。
被丢掉的角色的位置数据还在服务器端存着,但客户端不渲染。
服务器那边把这些角色的位置广播回来的时候客户端不知道该怎么处理,就出现了瞬移——角色在屏幕上的位置和服务器端的位置对不上,系统尝试修正的时候就直接跳过去了。”
他顿了一下,手指在桌面上轻轻敲了两下,又补了一句:“客户端本地算出来的位置和服务器发过来的位置中间差了一大截,系统每帧都在尝试把这两个位置拉到一起,拉不过来的时候就强制同步,那个强制同步的瞬间就是玩家看到的瞬移。”
梁永琪站在他身后。
“那把同屏渲染上限往上调呢?调到一千五或者两千。”她往前走了半步,视线落在屏幕上那个八百的数字上面,“服务器端能撑住一千两百个人,说明数据处理这块没问题,卡的是客户端渲染。
那把上限放开,让引擎多画几个人,问题不就解决了?”
李轩摇了摇头。
他的手从键盘上抬起来,搭在椅子扶手上。
“上限不是我们设的限制,是引擎的渲染管线本身扛不住。
每一帧要计算所有角色的模型变换、光照、阴影、动画骨骼,八百个角色同时渲染的时候引擎的帧预算已经用掉了七成,再往上加它会直接崩掉。”他停了一下,手指在扶手上收紧又松开,“帧预算这个东西是固定的,一帧十六毫秒,超了就是超了,没有商量的余地。
我如果把上限调到一千二,引擎会在第一帧就爆掉,不是卡顿的问题,是直接闪退。”
“但如果我把上限往下压,压到五百,长安城里就只能看到五百个人。
剩下的七百个人全部被引擎丢掉,玩家看到的是一座空了一半的长安城。
《梦幻》强调的就是热闹,长安大街上人挤人的那种感觉,如果砍掉一半的人数,那个热闹就没了。”他的声音低下去,像是在跟自己说话,“而且玩家不傻,他们会发现有些人明明在队伍列表里,在地图上就是看不到。
到时候论坛上全是帖子问为什么我队友站在我面前我看不见他。”
梁永琪靠在机房的门框上,两只手环在胸前。
她看着屏幕上那个八百的数字,没有立刻说话。
这个数字的上下两端各有一条路,往上走是技术崩盘,往下走是体验崩盘。
两条路都走不通。
她脑子里转了几个方案,每一个都在某个环节上被卡住——要么是客户端算不过来,要么是服务器广播量太大,要么是玩家体验打折打到没法接受。
她咬了咬下嘴唇,手指在手臂上轻轻敲了几下。
她拿出手机走出机房,在走廊里拨了陈浩的号码。
电话接通之后她把情况完整地说了一遍——同屏渲染上限、瞬移的成因、削减人数带来的体验损失。
她说的时候语速比平时快一些,像在把一堆积木一块一块地垒起来,垒完了等着对方推倒或者加固。
说到最后她停了一下,加了一句:“我这边暂时想不到两全的办法,李轩那边也卡住了。”
电话那头沉默了片刻。
梁永琪听到陈浩的呼吸声在话筒里均匀地传过来,中间夹着一声极轻的、像用手指敲了一下桌面边缘的声音。
那一声响之后又是几秒的安静,她能想象陈浩坐在办公桌后面,手指搭在桌面上,眼睛看着某个固定的点,脑子里在翻各种可能性。
“让玩家可以选择屏蔽其他人的特效。”陈浩说,“只保留自己和队友的技能特效,其他所有人的特效全部不渲染。
但是人物模型必须全部显示。
每一个角色都要看得见,只不过他身上那些花里胡哨的光影不用画出来。”
梁永琪把手机换了一边耳朵。
“特效的计算量比模型大?”她问了一句,手指无意识地在走廊的墙壁上划了一下。
“特效是叠加渲染,一层火墙上面再叠一层雷电再叠一层毒雾,每一层都要单独计算光线和透明度。
模型是静态渲染,一个人站在那里不动的话,他的模型每帧的变换量很小。
把特效砍掉之后引擎的帧预算能腾出很大一块,用来撑住全部的人物模型。”陈浩的声音从话筒里传过来,不急不缓,“你让李轩去翻一下渲染管线的代码,特效和模型是不是走同一个队列。
如果走同一个队列,把特效拆出来单独排队,优先算模型,特效往后排。”
梁永琪挂了电话之后走回机房。
走廊到机房的这段路不长,她走了几步就到了门口。
李轩还坐在主控机前面,屏幕上那个八百的数字还在闪烁。
她把陈浩的方案转述了一遍。
李轩听完之后没有立刻回应,他把手从椅子扶手上收回来,重新搭上键盘,手指在参数表上翻了几页,找到了特效渲染模块的配置项。
“特效计算和模型计算分离。”他说,手指在键盘上敲了起来,速度比刚才快了一截,“特效走单独的渲染队列,每一帧先算模型,模型算完了有余力再算特效。
玩家关掉其他人的特效之后,特效队列里只剩下自己和队友的数据,计算量降到原来的十分之一都不到。
模型队列不变,所有人的人物模型全部保留。”
他一边敲一边说,声音比刚才亮了一些:“特效队列如果来不及算就直接丢掉,丢掉的只是光影效果,人物模型不受影响。
玩家看到的是一个人站在那里但没有技能光效,这比看不到人要好得多。
而且特效丢掉的时候不会影响位置同步,因为位置数据挂在模型上面,模型没丢,位置就不会错。”
他没有再抬头。
梁永琪站在他身后看了一会儿,屏幕上代码行一行一行地往下滚,李轩的手指在键盘上跳得很快,偶尔停下来删掉几行又重新敲进去。
她看了一会儿,然后退出了机房。
那天晚上李轩没有离开公司。
技术组的三个人陪着他一起熬,机房的灯一直亮着,屏幕上的代码行一行一行地滚动。
凌晨两点多的时候有人出去买了一趟泡面,回来的时候拎了五碗,每碗的盖子都掀开了,热气从碗口升起来,在机房的冷气里凝成一片白雾。
李轩一只手端着面碗一只手敲键盘,面吃了一半就搁在桌角,汤凉了也没再碰。
旁边技术组的一个小伙子吃着面凑过来看了一眼他的屏幕,问了一句这个调度逻辑是不是要重写,李轩嘴里含着半口面含含糊糊地应了一声,手指没停。
凌晨三点十七分,他把最后一行渲染优先级的调度代码敲完,按了回车。
屏幕上开始跑测试。
测试场景是长安大街,预先加载了一千八百个角色模型,所有角色的特效全部按照“仅显示队友”的规则进行了裁剪。
渲染帧率从测试开始的第一秒就稳定在一个数值上,上下浮动不超过三帧。
他盯着那个数字看了十几秒,然后伸手把旁边那台测试机上的画面拖到了大屏幕上。
长安大街上挤着上千个角色,人物模型全部完整显示,每一个角色都在动,走路的、摆摊的、跑动的、站着聊天的,密密麻麻的人头从屏幕的近景一直排到远景。
画面没有卡顿,角色的移动流畅,帧数稳定在三十帧以上。
【跪求礼物,免费的为爱发电也行!】