《奧日與精靈意志》是如何完成近乎不可能的Switch移植任務的?
作者:託比亞,會音樂和遊戲設計的TA裡最帥的那位
本文首發知乎:https://zhuanlan.zhihu.com/p/260116904
一直很好奇Moons studios究竟是如何在遠端合作的狀態下保持高度的生產力並完成如此優秀的遊戲的,他們甚至在近期完成了近乎不可能的任務:讓Ori在Switch上在對畫面質量不怎麼做出妥協的情況下讓遊戲穩定60fps,真的好想一窺他們的Workflow是怎麼搭建的。
Switch與Xbox One的畫面比較,不僅差異十分的小,還穩定維持在了60fps
終於Digital Foundary回應了我的期待!他們在前幾天釋出了個視訊,就是關於Moons Studios在針對Switch上面的開發優化上做了哪些努力,並多少分享了他們的Workflow!於是興奮的我反覆看了視訊數遍後草草記錄下了重點。
遊戲引擎採用的是自定義的Unity遊戲引擎,並取名Moonity,是個完全圍繞Ori遊戲型別和渲染方式特別定製工作流及渲染管線的自定義引擎。
他們完全採用了Painter Algorithm的方案(由後往前繪製),結合Early-z pre pass規避Overdraw,並根據結果渲染成6張layers的RT,再與3D角色的RT layer blend在一起(不過由於層級的深度排序幾乎是固定的,似乎做了些離線操作減少了early-z的gpu壓力,至今沒搞明白具體做了什麼)。除了角色層以外,每個RT代表的layers都可以單獨設定解析度,不僅可以做出景深(Depth of field)的效果,還能降低GPU的負擔。
所有的場景都是由6層場景layers加上3d角色的layer,一共7層構成的,每一層都會渲染成一張獨立的RT
藍色的部分是early-z的結果,目的大概是在生成不同layer的RenderTexture的時候可以直接cull掉重疊的畫素
除了角色層以外,所有的layers都可以單獨控制解析度,從而形成DoF的效果,並提高了渲染效率
由於玩家在進行操作精度高且快節奏的遊戲時,視角基本只會集中在角色身上,因此遊戲就能通過視覺焦點的位置去切不同頻率(Frequency)的貼圖資源。大體操縱方法是:視覺焦點的周遭選高頻率的貼圖,其他地方就能替換成低頻率壓縮(Low Frequency Compressions)的貼圖從從而減少視訊記憶體的負擔。
距離角色近,也就是視覺焦點的附近選擇高頻率的貼圖,反之選擇低頻率壓縮後的貼圖
他們還進一步在每個場景設定了上百個攝像機的位置節點,來預計算並儲存每個場景物件對該鏡頭位置的貢獻度,這樣在遊戲中就能動態隱藏對鏡頭貢獻不足的物體了。
對該鏡頭節點貢獻度不足閾值的物體會被動態隱藏
接下來我們聊聊對Ori畫面質量提升最大的自定義光照,其中分為了靜態光照及動態光照,先從相對簡單的靜態光照開始。
靜態光照是手動畫上去的,美術可以直接在Unity中將光照畫在一個低頻率獨立的GI Layer上面,並且可以依據情況在遊戲中切換成低解析度的版本。
美術可以直接在引擎內繪製靜態光照資訊
而動態光照就比較Charming了,大體使用了兩個方法。首先美術會繪製角色6個不同面的受光資訊(前後上下左右),並把其烘焙到rgb裡(應該會是個atlas),根據光的位置與距離去進行插值,這也不算什麼新技術了,不過最終呈現的效果還是很讚的。
美術繪製了不同方向的光照資訊
根據光源的位置去進行插值
而光照的著色則是借鑑於Doom 2016中的Particle Lighting的技巧,Moons studio稱之為Tile light calling,大體是將不同深度及優先順序的光照資訊寫入一張Tile Atlas,再生成對應的Tile indices來索引和混合光照的顏色。相比於Xbox通過Compute Buffer計算並儲存Indices的方案,Switch則採用了一張低解析度的2D貼圖來記錄indices,結果上來說對畫質並沒有造成多大的損傷。
光照資訊的畫面,可以隱約看到不同通道的光照範圍是如何混合的
可能是團隊借鑑的技術,擷取自Doom 2016的分享。id software發現由於畫面中各別的粒子效果對畫面的貢獻程度是不同的,想到了根據距離及重要度等資訊將個別生成的光照資訊輸出成Atlas,並在繪製完粒子特效後重新疊加光照效果的方法,從而實現了高效優質的渲染效果,並且其渲染質量與螢幕解析度無關
有趣的是,所有的layers都是做的前向渲染,只有3d的角色layer採用的是延遲渲染。按照原視訊的說法,沒有統一使用延遲渲染的主要原因是延遲渲染會丟失真實的深度資訊,在逐Fragment計算Tile light calling時可能造成潛在的artifact。雖然沒有詳細說明,不過由於延遲渲染中,位置資訊會儲存在Fragment階段後所產生的MRT中的32位Float位置貼圖裡,是有資訊丟失的可能。
只有3D角色是延遲光照
遊戲中的Soft Physics是直接在Unity中繪製的,省去了從其他DCC軟體頻繁匯出的煩惱,並且整個過程是Undestructive的
在Unity中直接製作Soft Physics
God rays則採用了對多個幀做Stochastic Sampling + Blur,Stochastic Sampling是一種結合Poisson Disc(均勻取樣) + 抖動的隨機取樣方法,從最終的畫面效果來說也是可圈可點的。
優秀的2D God Rays將畫面的氛圍檔次進一步提高了
Ori的發光拖影其實就是一堆從頂點拖拽出的發光片,這裡借鑑了Keijiro大神的vertex based skinner方案,具體可以看https://github.com/keijiro/Skinner
拖影是一堆從頂點拖拽出的發光片
借鑑了Keijiro大神的Skinner
無處不在的拖影效果
Profiling 就更好玩了,他們首先定製了完整的In-Game Profiler工具,並且可以記錄足夠長時間的偵測結果,以客觀地量化當前的優化進度。
可自由拖動的In-Game Profiler
記錄多日的Profiling,從圖中可見遊戲效率隨著日子推移逐漸趨近於穩定
接下來,他們還製作了可以記錄每個場景當玩家處於不同位置的渲染時間,並分別記錄了各別場景的渲染峰值。由於Switch上的目標幀數是60fps,所以當渲染峰值高於15ms的時候,就會在場景上標記出來,這對開發人員偵測渲染效率的幫助是不言而喻的。
可以將每個場景及路徑渲染峰值記錄下來的Profiler
綠色表示的是玩家經過的路徑,除了記錄了QA Test的資訊外,他們還搞了個快速跑關的測試工具來重複並快速地檢測問題點。
飛起來吧Ori!給我查詢問題去!
為了方便對比XBox和PC平臺的畫面效果,他們順手拍下了各別平臺針對該峰值區域的截圖,並根據日期排序,以方便橫向對比優化前後及不同版本之間各平臺的顯示差異。
選擇顯示平臺及日期的操作介面
切換不同平臺對比顯示效果
最後的最後,來聊聊Ori的場景無縫銜接解決方案吧。首先遊戲會快取相鄰場景間相關資訊,以便於在遊戲中實時計算玩家與相鄰場景的距離,並預測玩家即將到達和遠離的場景來動態讀取或釋放遊戲場景。
計算玩家位置並預測需要預讀取或撤銷的場景
由於Ori是個快節奏高難度的動作遊戲,為了保證死亡能夠快速重啟,Ori的每個Checkpoint也會預快取周遭區域的資源,並在達到下個Checkpoint以前始終儲存在記憶體裡,也就造成了能夠記錄關卡資訊的記憶體就更少了,所以遊戲開始時候就需要做一些預快取來小心處理資源讀取可能存在的問題,不過這也就造成了開始遊戲的讀取時間會特別的長。結果上來說的確保證了遊戲的順暢性及場景無縫銜接的體驗,所以這種妥協肯定是值得的。
團隊正在通過放大攝影機的可視範圍及視覺化Safe Zone來觀察資源的載入情況
經常覺得周遭的開發者朋友們都在用苦癟的方式來開發遊戲,近期一直在尋找著能愉快地開發遊戲並方便自動化地檢測問題的workflow,Moons Studios的遠端合作方案的確給我帶來了很多的啟發,真心希望哪天我也能在家裡使用如此暢快淋漓的workflow來遠端開發我熱愛的遊戲吶!
原視訊地址:https://www.youtube.com/watch%3Fv%3DkH6wTpIObxE%26t%3D650s
相關文章
- UAVIA打造遠端操控軍用無人機,完成不可能完成的任務無人機
- NEO智慧合約開發(一)不可能完成的任務
- 不可能的任務?(轉)
- 餘承東想掌舵華為 任正非給他了一個不可能完成的任務!
- 《精靈與螢火意志》工作室:去中心化工作模式讓我們更靈活中心化模式
- 從《奧日與螢火意志》 沙蟲逃忙關卡看遊戲的節奏設計遊戲
- 目前待完成的任務們
- 如何精確理解leader佈置的任務
- Django 如何使用 Celery 完成非同步任務或定時任務Django非同步
- 用Django模型完成更多的任務Django模型
- 《精靈與螢火意志》開發者專訪:繼承前作血脈,擴充遊戲邊界繼承遊戲
- JavaScript的巨集任務與微任務JavaScript
- 如何高效完成領導安排的複雜工作任務?羅列待辦任務清單很有效
- Niantic:《精靈寶可夢GO》僅完成10%Go
- 精靈寶可夢是如何發展成世界頂級的遊戲IP遊戲
- NEO智慧合約開發(二)再續不可能的任務
- 用Pandas完成Excel中常見的任務(2)Excel
- Cornfox & Bros.如何將手遊移植到SwitchROS
- 驅動精靈是幹嘛的 驅動精靈怎麼安裝驅動
- 專訪《精靈與螢火意志》工作室:規模翻了三倍 系統全面進化
- 去阿里,是不可能的,這輩子都不可能的阿里
- 專案任務與運維任務的衝突運維
- 爬蟲學習日記(六)完成第一個爬蟲任務爬蟲
- 在不會使用excel函式的情況下如何完成複雜任務Excel函式
- 任務系統 / 擊殺指定數量怪物後完成任務
- 如何聰明地利用待辦事項 APP 完成任務APP
- 任務佇列,巨集任務與微任務佇列
- 面對遊戲移植,Switch的效能還有得“榨”嗎?遊戲
- Golang 入門 : 等待 goroutine 完成任務Golang
- JS中EventLoop、巨集任務與微任務的個人理解JSOOP
- 你應該入手一份《精靈與螢火意志》,但Moon Studios不應滿足於此iOS
- Flowable啟動流程例項和查詢任務以及完成任務
- win10驅動精靈不受信任如何處理_win10無法安裝驅動精靈任解決方法Win10
- 關於非同步方法中的巨集任務與微任務非同步
- 如何理解 JS 非同步程式設計的,EventLoop、訊息佇列,什麼是巨集任務,什麼是微任務?JS非同步程式設計OOP佇列
- 人性化-完成需要人類感官的任務的機器人機器人
- linux 如何建立定時任務?crontab -e 定時任務使用的時間是系統時間Linux
- SUID 與 SGID - 使普通使用者可以完成特定使用者許可權才能完成的任務UI