模擬遊戲如何優化?《醫院計劃》開發者分享

【Gamelook專稿,轉載請註明出處】

Gamelook報道/經營模擬遊戲是當下比較熱門的獨立遊戲品類,其中一些作品還加入了讓玩家創作內容的模式,比如Oxymoron Games在去年底發行的《醫院計劃(Project Hospital)》,就在Steam平臺獲得了80%以上的好評。

這是一款建造經營類遊戲,玩家們在遊戲裡可以同時成為一流的醫生、有抱負的建築師和成功的管理者,你可以設計屬於你自己的醫院,調整每一個細節或者使用預置模型直接行醫。為了經營醫院,你要聯繫不同的保險公司獲得更多帶有特殊醫療條件的病人,執行檢查、實驗室測試,並使用各種設備解決各種診斷難題,送病人住院,用手術和其他治療手段幫助病人痊癒。那麼,作為獨立團隊,如何處理這樣一款複雜的遊戲呢?Oxymoron工作室共同創始人Jan Benes最近在博客中分享了他們的一些優化技巧和心得,想要做建造經營類遊戲的同行們可以參考:

《醫院計劃》有著該品類遊戲的所有經典特色:玩家們創造的動態內容、大量活躍的角色和物體以及可拓展的UI系統。想要在不同設備上完美運行這款遊戲,需要大量的努力,而且也是非著名案例“凌遲”(a death by a thousand cuts,即每件事都不致命,但累積起來卻可以造成嚴重後果)的最佳案例,所以需要大量細節步驟,解決很多特殊問題,也需要在工具上投入大量時間。

模擬遊戲如何優化?《醫院計劃》開發者分享

性能指標:我們真正要實現的是什麼?

在研發的初期,我們設定了想要支持的場景,達到的性能以及硬件需求等目標。

我們的目標是可以至少100個全動畫角色同屏展示,最高同屏可展示300個角色,做一個100X100圖塊地圖,最高四層。並且希望,哪怕是在集成顯卡上,也能在最高幀率下實現1080P效果,這本身並不難實現,因為CPU才是最主要的因素,尤其是隨著億元的增長。現代的集成顯卡已經比較強大,只有到2560X1440分辨率的時候才會顯得吃力。

對於簡易模組支持,遊戲裡大多數據是開放的,這就意味著為了一些打包文件而犧牲了部分性能,但這似乎不會有太大的影響,唯一的問題可能就是加載時間更長些。

圖形

由於《醫院計劃》是一款經典的2D三維不透明遊戲,你可以想象所有東西都是從後往前渲染的,在Unity引擎裡,每一個圖形物體都需要設置正確的Z值(或者說是到攝像頭的距離)。在可能的情況下,不互動的物體會被放到不同的層面,比如不同樓層與物體和角色都是獨立的。

模擬遊戲如何優化?《醫院計劃》開發者分享

在垂直渲染的場景中,所有的幾何圖形都是用C#動態創作的,所以需要重建的幾何圖形頻率是兩個最重要部分的其中之一,第二個部分就是繪製調用(Draw Call)次數。

Draw Call

不管物體有多麼簡單,單個物體的繪製都要佔用一幀,這是最主要的限制之一,尤其是在低端設備上(再加上Unity本身也有額外佔用),最明顯的解決方案就是儘可能在一次繪製調用中批處理更多的圖形物體,但這麼做會帶來一些有趣的結果,比如可以批處理的物體和攝像頭的距離相同,所以其他圖形也可以在前面或者後面被恰當地渲染。

模擬遊戲如何優化?《醫院計劃》開發者分享

這裡列舉一些數字:在一個96X96地圖上,,理論上你可以放置9216個物體,這可能需要9216次draw call,批處理之後,調用次數降低到了192次。

然而,在現實條件下,這會變得更復雜一些,因為只有相同紋理的物體才能被批處理,所以結果並沒有那麼樂觀,不過,這種方法仍然是可行的。

模擬遊戲如何優化?《醫院計劃》開發者分享

大多數的批處理都是手動操作的,這樣可以控制結果,我們還是用Unity的動態批處理作為“最後手段”解決方案,但這種方法有利也有弊,它的確可以降低調用次數,但每幀都會多佔用性能,而且有些情況下不可預測。比如兩個與攝像頭等距重疊的精靈圖會以不同順序被渲染在不同幀,這就會產生抖動,而手動批處理是不會有這種情況的。

多樓層

讓玩家們能夠建造多層建築增加了很多的複雜性,但卻可以對性能帶來驚人的幫助。在活躍樓層,只有角色和武器需要動畫和渲染,醫院內活躍樓層上下所有的東西都可以被隱藏。

著色器

《醫院計劃》使用了相對簡單的定製化著色器,只有顏色替換等少數功能,比如角色著色器可以最多替換5種顏色(在著色器代碼中使用condition),而且這種做法的代價相對昂貴,不過,由於角色所佔屏幕的空間不大,所以通常不會帶來太大問題。這麼做也是非常值得的,因為不限制角色的衣服顏色也給遊戲環境和玩家角色帶來了多樣性。

我們還快速學會了避免設置著色器參數,並且儘量使用頂點色。

模擬遊戲如何優化?《醫院計劃》開發者分享

紋理質量

一個比較有趣的信息是,我們在《醫院計劃》裡沒有使用任何的紋理壓縮,在矢量圖形中特定紋理壓縮之後看起來的效果很差。

為了給內存低於1GB的設備節約GPU性能,我們自動把遊戲內紋理分辨率減半(UI界面不變),所以遊戲內紋理的質量是比較低的,而UI紋理保持了原本的分辨率。

優化CPU性能:多線程

雖然Unity的腳本邏輯基本上是單線程的,但你始終可以選擇直接用C#運行多線程。在遊戲邏輯方面,這可能不是一個好方法,但在某些形式的任務系統(Job System)裡,通常有一些非臨界時間任務可以從單獨線程運行中受益,在我們的案例中,我們為兩種功能使用了多線程:

尋路任務,尤其是大地圖和佈局不佳的環境,尋路往往需要數百毫秒,因此這個任務非常適合從主線程剝離出來,平行任務的數量需要考慮電腦硬件上的線程數量。

光照地圖也是通過單獨線程更新的,但一次只更新一層樓,這並不是一個重要的系統,而且房間裡的自動燈光會隨著緩慢更新而淡出。

動畫製作

我們在研發很早期的時候就決定使用2D骨骼動畫系統,在考慮了當時所有的動畫軟件之後,我們最後決定使用我在幾年前做的一個簡單系統(當時是業餘愛好項目),來滿足《醫院計劃》裡的特殊需求,基本上就是簡單的支持角色變化的Spine動畫。和用C#運行Spine一樣,很明顯這種方法比使用原生代碼的代價更高,所以在研發期間我們做了多次優化,幸運的是結構(rig)都非常簡單,每個角色大概有20個骨骼。

比較無厘頭的事實:當訪問單個骨骼的轉換時,最重要的一點是從地圖查找切換至數組中的簡單索引。

模擬遊戲如何優化?《醫院計劃》開發者分享

除了不給攝像頭之外的角色做動畫之外,另一個技巧就是藏在主UI窗口背後的角色也不需要做動畫,不幸的是,由於使用了半透明UI,我們在最終版本中沒能使用該技巧。

緩存

在可能的條件下,只有當影響數值的變化時,我們才會嘗試運行更為苛刻的計算,最好的例子可能是房間和電梯,當玩家們放置一個電梯或者牆體的時候,我們會運行泛洪填充算法,它可以標記電梯和房間可以使用哪些圖塊,這在隨後會加速尋路,而且可以用於向玩家展示哪個房間目前是不可用的。

分散、延遲的更新

某些情況下隔段時間運行特定更新是有意義的,我們使用的方法有以下幾個:

有些更新只需要在每幀在角色的一部分運行,比如病人一半的行動腳本只在比較奇怪的幀更新,另一半則在普通幀更新(同時動畫和動作都可以流暢運行)。

在特定情況下,尤其是角色限制但需要調用比較大量代碼時,更新只在特定時間內運行,比如每秒一次。

模擬遊戲如何優化?《醫院計劃》開發者分享

最昂貴、有時候也最普通的口令是每個病人的檢查評估,這裡需要衡量很多因素,比如一個部門裡的哪個職員正在忙、哪個設備目前被預約。這個信息對於所有的病人也是不尋常的,因為他們的主治醫師和他們的語言能力也是有影響的。有時候你需要檢查的東西有很多,所以更新只在少數幀運行,而且在下一幀繼續。

結論與心得

優化一款帶有大量互動元素的建造模擬遊戲是個持續的過程,通過使用Unity裡的工具集,並且解決最糟糕的障礙,成為了我在研發過程中的常規任務。

雖然遊戲研發總有提高的空間,但我們對於目前的結果是滿意的,遊戲的運行符合我們原定的目標,玩家們也經常給遊戲做模組,極大超出了原有角色的限制。

或許值得一提的是,即便是和我曾經從事過的3A遊戲相比,我覺得《醫院計劃》也是我見過最複雜的玩法邏輯,所以很多問題是特定項目才出現的,不過,預留足夠的時間做優化是任何項目都需要做的。

相關推薦

推薦中...