將遊戲機制和幀數綁定,給玩家們製造了多少的樂子與麻煩?_風聞
游戏研究社-游戏研究社官方账号-1小时前

配置升級了?那麼時間也要開始加速了。
在Steam上收穫佔比四分之三的差評過後,Roguelike名作《雨中冒險2》的新DLC《風暴探尋者》毫無疑問算是做砸了。

好評率最低跌到了24%
國區更是隻有8%
假如僅是DLC更新的關卡、倖存者和敵人存在問題,那不買DLC便罷。
然而《雨中冒險2》的本體隨DLC的上線一併迎來強制更新,順帶接入數不清的Bug和錯誤,包括但不限於:隨機猝死,掉幀卡頓,紋理缺失,物品不再高亮,關卡變得更難攻略,最終Boss“米斯歷克斯”莫名無敵……
結果《雨中冒險2》本體的近期好評率也被拖累到了“褒貶不一”的水平。

原作者Hopoo和他的團隊在兩年前將《雨中冒險》系列的版權賣給了發行商Gearbox,所以《風暴探尋者》是完全由Gearbox操刀的第一款《雨中冒險》DLC。現在Gearbox不僅需要承受來自Hoppo跟玩家們的怒火,還得擔起全責,修復他們自己給遊戲帶來的新問題。
8月30日,即《風暴探尋者》上線兩天後,Gearbox發佈了一篇開發日誌。日誌列出的海量問題中,第一條且最致命的一條如下:
“遊戲中的許多元素都受到一個Bug的影響,這個Bug會導致它們的行為根據玩家的幀數而改變。這些要素包括物理系統、攻擊速度和移動。”

“下個補丁會修”
官方用了一週時間才修好這個Bug。在這一週裏,他們推薦的權宜之計,是在設置裏鎖定遊戲運行幀數至60幀。僅在60幀下,《雨中冒險2》的宇宙才會按照原本的節奏平穩運行。

而在不同配置的電腦所帶來的不同幀數下,遊戲內發生的一切也將產生加速或減速。倘若取消幀數限制、放任幀數隨意增長,這個宇宙便將在加速的熵增中製造無盡的混亂和災難,氣得難以招架反覆重開的玩家倖存者們捶胸頓足——
將幀數和機制強行綁定在一起,會給遊戲帶來深重的災難。想説明白這條真理並不是件容易事,但這個Bug版本的《雨中冒險2》提供了絕佳的範例。
1
大體來説,因為玩家角色性能受到幀率影響,許多角色在高幀率下都得到了加強,乍一看搞得《雨中冒險2》像是一款變相的“P2W”(氪金致勝)遊戲,電腦配置越好,角色跟着越強。
高幀率下,角色的武器射速和技能冷卻時間也都得到了普遍加強。比如,武器射得更快,位移閃現技能飛得會更遠。“工程師”的跟蹤魚叉提升了鎖定速度,“嗆鼻毒師”的吸血技能也加快了吸血速度。

30幀和450幀下“指揮官”R技能的射速對比
Youtube@Neon Shockz

高幀率下轉起來了的“裝卸工”
Youtube@Neon Shockz
像“船長”的霰彈槍,需要通過蓄力縮小彈丸的擴散範圍。但在高幀率下,彈丸的散佈面積比以前更加集中,推測是縮小散佈的公式也受到時間影響,隨着幀速率提升發生了數據變動。

圖源Reddit:u/bataloof
而在鎖定30幀的情況下,這些技能都會變弱,弱到有些滑稽的地步。

“僱傭兵”的起飛變“陸游”
Youtube@Neon Shockz
按理説,《雨中冒險2》不算是太新的遊戲;雖然是具備超大數據計算量的肉鴿,但不去刻意刷道具死堆角色屬性的話,也尚不至變成“顯卡殺手”。高幀率帶來的高角色性能,理應算作一次具有普適性的增強。
可是受到幀率影響的,不僅只有玩家這一邊。
有些敵人在高幀率下倒是變笨了,只會反覆起跳停在原地。也許有一行代碼決定敵人每隔幾秒起跳一次,而過高的幀數大幅縮短了敵人的起跳間隔。

Youtube@Neon Shockz
但敵人的數量(生成速率)和質量都在產生質的飛躍,讓玩家們猝不及防——猝是猝死的猝。
許多敵人都有鎖定玩家後立即發射的激光,在高幀率下,激光的鎖定速度快得出奇,幾乎無法躲避。前期Boss“石巨人”同樣擁有激光攻擊,還是每幀都要計算的持續性傷害,高幀率時出傷速度也跟着提升,瞬間蒸發玩家角色的血條。

*慘死*
Youtube@Neon Shockz
另一個飛行Boss“漫遊者”瀕死時會釋放超新星爆炸,對附近目標造成致命傷害,前期威脅巨大,但它爆炸前會留出一段時間供玩家規避。高幀率會縮短這段時間,讓這個自爆攻擊變得躲無可躲。

蓄力效果都沒顯示完,它就爆炸了
Youtube@Neon Shockz
類比這兩個Boss,敵人也都隨着幀率上升得到屬性增強,增強的力度還遠勝過玩家方,秒殺玩家的情況十分多見。
不僅如此,包括一些地圖上的中立設施,也會因為幀率問題無法正常工作。

“跳板在高幀率下無法工作”
倘若出於各種因素(比如疊了幾十層數值道具、後台跑了太多程序)導致幀率降低,雖然敵人性能也會下降,但玩家的性能也會跌到離譜的地步,乃至跑都跑不動。總之不鎖60幀的話,Bug版本的《雨中冒險2》玩着太難了。
既然説是Bug,就意味着遊戲代碼中的某些地方出了問題。比起Gearbox要花一週時間才能修好問題的程序員,有一批人對代碼層面的東西更敏感。他們是《雨中冒險2》的Mod作者,不下半天就找出了Bug來源。
問題出在《雨中冒險2》使用的Unity引擎。簡而言之,Unity引擎下有兩個函數:Update和FixedUpdate。在Update函數中的所有操作都是按幀調用,而FixedUpdate則以固定的、預設的現實時間(或稱固定時間步長)進行調用,默認是0.02秒調用1次,即1秒50次,頻率可以修改。

60幀下,Update每幀(約0.01666秒)調用一次
FixedUpdate則不受幀數影響
Gearbox有意在這次大更新將《雨中冒險2》升級至最新版Unity,卻好心辦了壞事。改代碼過程中,程序員自作主張插入了一大堆額外函數,改着改着,就把本該用FixedUpdate調用的、按現實時間計算的數據,混淆成用Update、結合幀數計算了。

“為什麼”
發現並在Reddit上曝光這一點後,從Mod作者到普通玩家們無不又驚又氣。
因為搞清楚Update和FixedUpdate的區別,是Unity開發者的必學基礎課程;將遊戲幀數和機制脱離綁定,或者説將遊戲畫面顯示的“渲染幀”和程序計算的“邏輯幀”脱離綁定,也應該是現如今每個遊戲開發者的必修課程。

某模組作者的直球辱罵:“他們是低能兒嗎?”
2
Unity是一款足夠成熟的引擎,將遊戲邏輯和渲染、機制和幀數脱鈎的相關功能做得十分完善,網上的教程也一搜一大把。
然而幾十年前的遊戲開發者可沒有現成的引擎和如此理想的開發條件。他們也根本沒可能意識到幀數綁定遊戲機制可能釀成的災難。因為幀是程序運行和畫面渲染的基本單位,把遊戲裏發生的一切跟幀數聯動起來也天經地義、順理成章。
網上能夠搜到的、建議開發者將幀數和機制脱鈎的英文教程,最早可以追溯至2004年。那個世代屬於PS2、Xbox初代和NGC(任天堂Gamecube),PC遊戲也方興未艾。

“修復你的時間步長!”
而在這個世代及以前的絕大部分遊戲,永遠將幀速率和遊戲機制綁在一起。就和臭名昭著的“千年蟲”(Y2K)問題一樣,遊戲開發者更多考慮當下而非將來的需求,而玩家們尚沒有能夠顯著提升遊戲幀率的設備。
像是FC這類復古主機,或者同時代的街機,機能相對受限,一旦遊戲畫面出現了太多運動的物體,遊戲畫面就會卡頓,幀數暴跌;不僅如此,遊戲裏的物理時間、物體運動速度也會一併放慢,進入“子彈時間”。
這即是幀數綁死遊戲機制導致的,要慢一起慢。不過玩家們並沒有因此吃太多虧,“子彈時間”偶爾也能幫助玩家及時反應做出救命操作。

FC掉幀王《魂鬥羅力量》
手柄開了連發也會因為掉幀丟一部分傷害
21世紀初,玩家所能擁有的硬件設備,特別是PC設備,迎來了突飛猛進的發展,在60幀以上運行遊戲不再是夢。可運行在這些設備上的“老”遊戲,開始出現數不清的問題。
從30幀到100幀,問題其實還不是很大,一些擁有以當時標準來看算高配電腦的玩家,早早利用起了高幀數或固定幀數帶來的優勢。
像是在世紀初頭幾年的FPS遊戲,角色的移動速度都會受到幀數影響。在CS1.6的經典地圖之一“de_nuke”,也就是後來的“核子危機”,T陣營出生點右側有個十分陡峭的斜坡,只有60幀以上的電腦才能向上爬;假如電腦僅帶得動30幀,這輩子都別想上去。

都市傳説是真的
《雷神之錘》和早期幾部《使命召喚》屬於另一種情況:將幀數鎖定在一個特定的數值時,角色會比平常跳躍得更高、更遠。
這是由遊戲結合重力計算玩家速度和向量的公式所決定的。以《雷神之錘3》舉例,在幀數設定為125幀時,玩家能夠跳躍至60幀環境下不可能到達的平台。因為這遊戲的速度計算公式在每幀最後都要進行一步四捨五入,而在125幀下得到的數據會取更多的“五入”,造成略高於預期的誤差。

無限制幀數,不行;125幀,彳亍

按公式算333幀下玩家角色跳得最高,但沒必要
圖源Youtube@Matt’s Ramblings
從100幀到300幀,遊戲就會像Bug版《雨中冒險2》那樣,運行速度整體變快,偶爾陷入無法攻略的混亂中。好比上百幀運行時的GTA老三部曲,主角的移動速度、造成和受到的傷害都會提升,任務的倒計時也會加速流逝,再加上一系列Bug,給玩家徒增麻煩。

死於大跳的冷麪殺手
Youtube@nikitozz

無法正常索降的精鋭特警
B站@R星老清子

水壓不足的消防車
B站@R星老清子
從300幀到3000幀,由於逐幀播放的菜單動畫也加了速,屏幕前的玩家甚至沒辦法選中“開始新遊戲”的選項,更別説玩了。

平均4000幀下一路疾奔、逃脱不出演示動畫的《東方紅魔鄉》
包括一些在主機端以30幀運行的老遊戲,如果強制搬到PC端的模擬器,再以60幀運行,也會冒出各種各樣的Bug。
想讓遊戲變得正常,要麼想辦法重寫代碼,先讓一部分重要的機制和幀數脱鈎,起碼讓遊戲能玩得下去,但這一招優化成本太高;要麼用各種遊戲內外的手段強制鎖定遊戲運行幀數,比如官方提供的硬鎖和垂直同步功能,以及民間自行開發的模組,做到低成本甚至零成本。
由於過時引擎的底層代碼留下的永恆限制,想讓一些老遊戲提到60幀運行都成了奢望。
例如《命令與征服》和《紅色警戒》系列所使用的引擎,就會逐幀推演時間流逝,頂多跑30幀,多不了一點。倘若強行使用某些工具突破幀數限制,單位的動畫跟AI的操作都會變得鬼畜起來,只怕玩家還沒操作造出第一個動員兵,對面就派出坦克把玩家基地送上天了。

最快速度=鎖30幀
3
就算在十幾年後的現在,遊戲行業也無法擺脱幀數的無形大手。只要不影響極端配置下的遊戲體驗,鬧出《雨中冒險2》那樣的笑話;或者能夠通過鎖幀等手段掩蓋可能出現的問題,遊戲開發者大多會對這個問題睜一隻眼閉一隻眼。
不是高手或速通大佬的多數玩家,想必都不太會在意,《怪物獵人:世界》裏太刀的登龍或弩炮的貫通彈在某些幀數下少跳一次傷害數字,或者《生化危機2重製版》里昂的小刀在120幀下傷害比60幀要高。

速通網站都要留個單獨的120幀選項以示嚴謹
卡普空近年來的3A大作所使用的RE引擎,也是一款常見的會受幀數影響遊戲機制的引擎。這款引擎中的大多數代碼其實都是基於現實時間而非幀工作的,但卡普空還是把最重要的動作和傷害判定部分交給幀數來操控。

《怪物獵人:世界》貫通彈跳傷害次數也隨幀數變化
Discord:Moonbunnie0001
事實上,不少的遊戲引擎都採取了類似的雙軌制,將一部分跟遊戲邏輯相關的機制交給現實時間,將另一部分需要嚴格且忠實地渲染在畫面中的機制交給幀數。
無論是在歐美還是在亞洲,遊戲開發者都普遍不願放棄幀數對遊戲機制的影響。這並不一定是因為他們犯懶。
首先“祖宗之法不可變”,許多十幾年前的引擎如今還在用,代碼修改難度和成本實在太高。例如《命令與征服》進入3D時代所使用的SAGE引擎、卡普空的RE引擎,乃至B社的Creation引擎、R星的RAGE引擎、FromSoftware自研的祖傳引擎,都會因幀數變動產生物理機制的變化。

《黑暗之魂2》舊版本的武器耐久度會在60幀加速消耗
但這一點是可以被修復的
何況這世上從來不是隻有PC玩家。主機幀數穩定,主機玩家沒理由考慮在60幀以上運行遊戲的問題,一些將主機玩家視作主要用户的遊戲,根本不需要考慮脱鈎的這一步。
而且這一步説着容易,實則意味着要讓開發者多寫成百上千行的代碼。這些代碼會對硬件造成額外的負擔,佔用大量性能,提升單平台或多平台的優化難度,乃至拖累遊戲渲染,造成畫面撕裂。
那些注重動作渲染的遊戲,包括《街頭霸王6》這樣格鬥遊戲在內,更不可能冒着破壞動作同步和流暢度的風險,將逐幀進行的動作強行綁定現實時間。比起浪費時間優化代碼,開發者寧願採取更簡單粗暴的鎖幀技術,避免高幀率設備破壞遊戲平衡性。
所以,即便Unity明確區分了幀數調用和現實時間調用的兩種函數,用Unity打造的《原神》和《永劫無間》最終還是變成了“高幀數等於高攻速”的典型代表。

《原神》不同幀數下的攻速對比
B站@紫菜蛇皮湯
另一個使用Unity的知名作品《絕地求生》,在多年前其實也有幀數影響武器射速的説法,好在這一點最後靠着持續的優化調整得到了修復。
什麼時候這一點不需要修復呢?當然是故意把幀數對遊戲機制的影響,做成遊戲設計的一部分。目前看來,估計也只有那些玩梗的Meta遊戲,想到反其道而行之,用這套系統逼着玩家拉低幀數。
2020年的比薩互聯網節日遊戲大賽上,一款叫做《讓我卡頓》(Make Me LAG)的小遊戲取得了一等獎。在這款橫板遊戲中,主角僅在60幀以下時才會開始行動,要求玩家採取手段調控遊戲運行的幀數,進行移動、跳躍、攻擊等操作。

45-59幀移動,25-44幀跳躍,1-24幀攻擊
國產Roguelike遊戲《清零計劃2》於今年推出的更新中,也添加了“幀數越低傷害加成越高”的詞條設計。

幀數和遊戲機制之間剪不斷理還亂的關係,不一定非得是令遊戲開發者頭疼幾十年的夢魘,也能變成鼓勵玩家積極利用的巧妙設計,是開發者的挑戰,但某些情況下也是機遇。
要我説,《雨中冒險2》也是肉鴿,比起掩蓋過去的錯誤,不妨把Bug代碼留個備份。《雨中冒險2》擁有一個神器機制,神器相當於《雨中冒險2》的內置修改器,能夠徹底改變一局遊戲的體驗。將遊戲機制綁定遊戲幀率的Bug,以及這個Bug帶來的混沌宇宙,就挺適合做成一個官方神器,既有樂子,又有誠意。

不過想不想做和能不能做是兩碼事。古往今來那麼多的遊戲開發者,都無法解決幀率和遊戲機制的問題;對於修這個Bug都能修上一週的Gearbox程序員,還是不要給他們添加太多工作負擔為妙。
他們能讓《雨中冒險2》走出代碼錯誤和Bug滿天飛的窘境,玩家們就知足了。
部分參考資料:
https://gafferongames.com/post/fix_your_timestep/
https://gameprogrammingpatterns.com/game-loop.html
https://docs.unity3d.com/Manual/ExecutionOrder.html
https://docs.unity3d.com/Manual/TimeFrameManagement.html
https://www.reddit.com/r/Cynicalbrit/comments/3dqwga/the_fps_lock_what_it_is_why_should_you_avoid_it/
https://www.youtube.com/watch?v=he02vJvKaRs
https://docs.google.com/spreadsheets/d/e/2PACX-1vSM-BTBvmvsovRJ2SaYdLLutC_CImTKpFh4GXcb3bNimjvbb54hGNFb2Nwne2zBJIkPR00zKGxOO4C0/pubhtml