爆款的誕生:《胡鬧廚房2》的多人遊戲模式解決方案
David Smethurst:我叫David,我是Team17的總監,我是負責程式設計內部的工作,與我們的合作伙伴合作。我的演講是有關於《胡鬧廚房2》的一些內容。
最早《胡鬧廚房》是由Ghost Town Games開發的,這是一款多人合作烹飪的益智類遊戲,我們大概可以讓4位玩家同時在一個遊戲中多個步驟準備烹飪。這個會比較有意思,它也獲得了很多的獎項。遊戲本身是非常成功的,但是我們的玩家對它有很多的期待,Ghost Town發了兩個DLC,但是仍然覺得不夠。所以接下來在續集中我們想要做什麼呢?
這是續集中Team17所做的工作,我們對續集很感興趣,我們希望和Ghost合作,希望提供一些功能集,讓更多的人蔘與遊戲。讓玩家可以在世界各地通過網路連線來合作,但是他們仍然可以進行本地遊戲。多人線上互動它是遊戲核心的功能,當然,我們希望在關卡中設定更多豐富的內容,而且有一些人已經在不同的地區和分解的關卡中有不同的進度,但是我們還想要做得多一些,所以我們在關底設定了動態“英雄”的關卡。
氣球的關卡是遊戲設計的第一個原型關卡。在飛行的過程中,玩家的角色就是這些廚師,他們是放在籃子裡,隨著時間時間的推移,暴風雨進來,繩子被卡住,籃子落到地面,佈局和需要製作的食譜也發生改變。這是《胡鬧廚房》Team17所做的工作,我們加入更多的內容,也做了更多的設計,我們將玩家相互分開,你需要在這些環境之中來找到切分的可能。比如說我們引入阻隔和間隙,讓我們在準備區和烹飪區分離之前進行食材的傳遞,這裡面我們也是設定了時間的限制,包括一些新的廚具和一些可以投擲的道具,一些物品我們也進行了迭代。所以我們可以通過各種挑戰的設定,來達成我們的目標。
我們還需要跨越不同的邊界,運送食品到另外的一部分,或者是讓玩家自己來計劃他的一個方案。穿過兩個部分之間的間隔,然後回到自己的區域,當然,我們還需要設定更多的食譜,所以我們加入了像壽司、漢堡、披薩、新的工具還有烤爐等,地圖也有變化。為什麼要這樣做,或者是為什麼這樣做續集,因為遊戲本身是受歡迎的,它很有可能是具有很好的前景,他已經建立好了自己的品牌,所以他會取得更大的成功,而不是因為之前的成功自滿而斷送了機會。
這些是Team17之前所做的工作,《Worms》我們開發了21個版本,我們可以看看Alien Breed,還有《胡鬧廚房》的人員,我們完成了原版新功能的新增。而且我們將它做得非常成功,這當中,團隊的整個成員都參與到了這當中。
我們實施的一部分,首先要解決風險最高的部分,就是聯網。我們先是從原始程式碼庫開始,希望能夠保持遊戲本身的機制和感覺,但是我們需要增加多人線上,而不會損壞這樣的感覺,所以我們是非常需要去有網路方面外掛的增強,我們可以使用Unity或者是完全重新編寫,因為考慮維持到原版的機制,重新編寫不太可行,所以我們來看看第三方外掛,這裡有幾個選擇:Photon、Ulink、Forge和Darkrift,這幾個外掛要考慮到成本,有些是雲平臺的付費,我們是多平臺釋出,要保證相容,所以外掛使用要考慮到重要的因素,就是你要對原有的程式碼進行相容,如果是有過多的設定或者是讓遊戲更加複雜,那我們的開發時間受到更大的影響。另外是大量的開發人員在解決方案上是可以幫助我們將它設定到最好,另外Unity有一個高階的API,就是HLAPI,通過它進行網路連線同時也進行很多工作的同步,包括變數的協調。新的程式碼庫也有大量的工作要做。接下來就是傳輸層,而且還要考慮到像平臺的套接層,以及比較低層級平臺上的表現。這是在Unity中可用的傳輸層之上的網路層,我們需要完全控制,並且決定每一個平臺上的具體細節,而我們內部的程式設計師也在開發這樣的專案,同時我們也會培訓其他的成員來提供內部的支援,來共同達成我們的技術需求。
現在,我們來看看網路拓撲。因為這部分是在網路構建中非常重要,我們需要了解它決定了遊戲何時是需要去進行通訊和協作的,還有就是我們的資料以及頻寬方面的限制,我們採用的雲託管伺服器需要非常小的頻寬,因為客戶包來回傳遞這會導致成本非常高,每一次都會因為新加入的玩家來遇到更大的頻寬要求。另外也要保證所有的遊戲端都要可以充當服務端,每個端都有物件,在所有點都有所有權,然後在單點保證資訊的傳遞,因為它是多向的,非常混亂。所以我們採用cs結構的網路拓撲的形式,然後對客戶包進行調整,它是直接適用於遊戲當中的物理物件,我們選擇拓撲結構是因為他們適合我們的需求。這也決定了我們使用原始的遊戲的程式碼,就可以保持原有的感覺,這對我們來說很有意義,可以進行不同的模擬。另外是程式碼在不同伺服器上的相互移動,也可以更加高效。
最後是更高層級的網路上,通過Unity在傳輸層上傳輸自己的解決方案,我們有一種辦法讓原本的指令碼在網路環境下工具,而不需要對這些指令碼進行破壞性的修改。我們使用增加額外的元件的方式來進行擴充套件。這也意味著對每一個原始的元件我們做出三個版本,一個是服務端,第二個是客戶端,第三個是原始功能。我們的伺服器使用全部三個版本,其他的端是使用兩個版本。當我們使用Unity時,我們為遊戲當中的每一個物件新增網路元件,以便提供唯一的網路標識。我們還提供了客戶端版本,如果將現有元件加入當中,這些遊戲已經預先應用到了廚房設計的預製件,無論遊戲物件如何使用遊戲的指令碼,我們都希望網路程式碼在所有的層級當中順利移動,這也意味著說,我們會通過在載入關卡時對場景進行掃描的方式,來增加網路元件。我們迭代場景中的所有物件,對於每一個物件,我們都會新增server元件或是client元件。這就是無論我們如何捕獲這些例項,無須檢查每一個資源,也不用告訴設計師和美工,如何在我們的GameObject上做出修改才能聯網。之後我們做《胡鬧廚房》續集時,從第一天我們希望遊戲保持這一狀態。現在這一遊戲仍然是可以在單機平臺上執行,同時也可以支援多人線上遊戲,同時我們的功能在開發時進行網路測試,在完整的烹飪管道中能夠足夠地去完成它的工作,而避免說在實際的平臺上執行不了的情況。
這是我們新的網路層,現在通過掃描和設定場景中預先存在的物件新增多人支援,同時也需要在關卡中生成新的物件,因此建立新物件的級別中是可以生成一些預製的遊戲物件,列表來完成目標,同時通過網路生成新物件引用列表。聽起來很簡單,但是需要確保所有的客戶端,在所有的衍生物件上都能保持同樣的ID,這樣就意味著說我們的網路、資料的路線非常重要。當遊戲執行時,接下來就要進行網路的驗證,我們必須重新編寫所有的程式碼,我們首先是要支援移動玩家的平臺,同時我們還需要支援各種不同的物理物件。比如說像有些物品的掉落,比如說移動,還有玩家在廚房當中扔食材等。我們建立了一個系統,客戶將他們的輸入傳送到伺服器,並且進行整個模擬,向周圍傳輸結果。這樣的話,我們就有可能面對一個滯後的問題,在等待伺服器物理結果傳輸回來,我們還允許他們在伺服器上直接移動,以響應本地的輸入。唯一的一個問題是,物體放在遊戲環境中他們會移動或者是旋轉,因為他們沒辦法平滑地在平臺上相互移動。為了解決這一問題,我們在所有的物體上都是通過統一平臺,來防止物體旋轉滑過的時候發生誤差,而且廚師也會在他們的平臺上移動食材,如果不能讓廚師和食材移動的時候,就會出現情況。我們可以檢測廚始和空間的定位,將廚師角色和物體同時移動,在這當中進行了大量的迭代和測試,特別是低頻寬情況下,遊戲的玩家也沒有發現誤差,但是仍然出現一個問題,兩個玩家相聚比較晚就會出現一些解決不了的延時的問題。
接下來看看網路的功能,效能我們希望保持穩定,尤其是幀率的穩定,玩家玩遊戲希望流暢的體驗,而網路的速度是比較穩定的。我們有很多頻寬,但是我們要保證資料傳輸量不要太大。那我們原始的遊戲是將各個預製件水平拼湊在一起,所有的站點都是單獨的物件。那麼在這裡,我們需要大量的繪製呼叫,因此,執行的效能是比較差的,為了能夠幫助美工建立了一個地板編輯器,就是說可以在場景的檢視中編輯地板的位置,這樣我們可以做計算,我們可以進行視覺化的處理。那麼我們也確實是傳遞給美術,我們必須在Maya中建立整個物件的FBX的檔案,然後匯入到Unity中。而不是在編輯器中編輯,並且將物件簡單地組合在一起。
但是為了解決我們在繪製耗時,我們依然需要做效率上的提升。比如說我們的美工他們需要更多的紋理和共享材料,我們會由渲染器進行合批,另外為了在滿足美術的要求的同時,達到能在最差的平臺執行的標準,我們選擇了配合ForwardRendering使用烘焙光照。為了輔助烘焙過程,我們會有專門的工具在專用的機器上執行。另外我們是有一個編輯器工具,他們是強制在預製的物體上應用正確的設定。比如說它強制設定MotionVectors選項為”Camera motion only”,以防止的TAA中的額外DrawCall開銷。我們要求所有的美工關閉靜態物體的Light probe功能以防止合批被破壞。我們還要求美術對所有不對場景產生明顯畫面影響的物體關閉陰影,這不會影響主要的操作區域的視覺質量。並且我們進行定期Profile分析,來確定瓶頸在什麼地方,並且我們也要確定未來一個開發更好的改善機會是怎樣的。
我們在使用Unity的Profiler的時候,也會去進行特定平臺的Profiler的研究,在進行遊戲的時候,我們還要去進行關卡和關卡效能的檢查,那我們設計了簡單的效能、跟蹤的系統,這個系統在一個關卡中對FPS進行取樣,關卡結束向玩家(這裡指的是QA)彙報統計的資料,這是分不同的幀數範圍來進行彙報,還有幀數波動等等。同時我們也會進行質量的檢查,另外我們還會收集標準差,幫助我們評估幀速率的檢查。有時候這些測試可以自動化地進行,而且可以非常快,容易規劃,另外就是在夜間可以完成,這樣的話,很容易去幫助我們提交資料。在這部分,目前一切進行很正常,但是實際上我們仍然遇到困難,比如說專案結束時發現特定關卡的CPU的效能出現在渲染問題上,對這些問題我們確認以後很明顯是DrawCall瓶頸,部分物體還是基於Prefab拼接,而不是在Maya中作為一個整體制作。在Unity批處理材料時,沒辦法在低端機上繪製足夠多的DrawCall。之後我們做了很多美工方面的工作,因為我們的記憶體資源是豐富的,我們選擇將相同的材質的物件合批,這樣我們就可以減少不需要資源的浪費。
在可能的情況下,我們還去進行了網格的調整,儘可能合併和減少資源的呼叫,在平臺的低端平臺上執行時依然還是會面對很大的挑戰。因為我們內容的創作者它想要實現更多的東西、更多的內容和更多的光照效果和細節。所以我們必須在統一的渲染管線中實現操作。所以在這裡很重要的一點就是渲染功能,因為我們低端控制沒有大量的記憶體,幀速率降低,而且我們考慮效果的時候是需要壓縮的,一開始進行的測試它是採用Forward渲染的,通知渲染了除太陽以外的所有燈光,最初在照明方面我們取得了很大的進步,包括深度緩衝區等。另外我們還必須在後期效果上進行驗證,就是使用Depth+Normal,最初使用這些工具降低了成本,但是仍然是有效率和時間的問題。然後我們最後的結果就是包括大量的繫結陰影,雖然說螢幕空間的陰影對於我們的陰影效果非常有用,但是它是比較花時間的。尤其是在這一過程中,我們是進行了一些常規的陰影貼圖。那麼我們所選擇的是在這個工具箱中的陰影,陰影的解析度非常高,我們取樣一次shadowmap,通過雙線性插值時陰影變得柔和,來保證視覺效果相同。
最後一個問題是後處理,最初花費了10毫秒,降低Quality設定,在每一個畫素上做更少的讀入和其他的優化,會讓整個的速度都會更好一點,但是很明顯,我們需要一個新的解決方案。同時你可以看到SSAO是唯一的一個後處理管線當中需要法線的部分,所以如果我們可以去掉這個步驟,我們就可以簡化pre-pass。我看評估了volumetricobscurance方案,一種極端簡化的SSAO技術,是非常方便而且容易實現的SSAO技術,它由CryTek針對XBOX360和PS3開發,這樣的一種方法解決了我們高樣本的需求,同時使得定製的發生器的輸出,只需要4個樣本就可以獲得非常好的結果。那TiltShift也是經常使用的,經常5毫秒以上,最低質量的設定中也是如此,也是要優化它,不然我們的美工也是無法控制和使用的。他們只需要在底部和頂部使用這一技術,在我們的攝像機下,也就是最近和最遠的區域,我們採用最新穎的方法,因為我們選擇不將它全部變成全屏後處理效果,相反地我們渲染了兩個四邊形,一個在底部一個在頂部,其效果的覆蓋40%螢幕的區域。進一步的優化是,其實我們並沒有實現一個正確的景深效果,我們研究了一些2000年初的技術,你只要在模糊紋理和清晰紋理之間進行雙線性插值,就可以得到一個從模糊到清晰的景深過度。最後一個改進是把postprocessing stack中的FXAA的檔案拿出來修改,強制它使用主機的code path。預設的實現是使用最高質量的實現。這個修改必須在原始碼中進行,因為這些介面沒有暴露出來,也不會受任何Quality設定的影響。
剛才講到了美工的原則,就是減少網格的複雜度以及合併DrawCall。另外我們區分了渲染用的網格以及碰撞網格,主要是為了減少碰撞耗時。我們在網路層其中的增加的一部分關鍵就是更新管理,這個概念在開發後期新增到遊戲中,當我們通過系統向遊戲中新增大量的邏輯和修飾元件時,我們自然會增加場景當中實現了MonoBehaviour的Update方法的元件數量,這回導致引擎從C++跳到C#的回撥增多,效能不是特別好。所以我們每一個網路元件實現了UpdateSynchroniser介面,而不是通過MonoBehaviour的Update方法。通過這樣的修改,大大減少了元件所花費CPU的時間。我們還在載入介面增加了一個額外的步驟,這個步驟就是掃描場景當中某些關鍵元件當中的某些關鍵例項,並且儲存它們的引用,這對玩家互動程式碼很重要,因為每一幀,我們都必須掃描所有的可以跟玩家互動的GameObject。對於遊戲當中的物件,預先儲存的引用陣列大大減少了分配。還有一個非常重要的改進,就是把委託放在一個List中,而不是使用+=,-=的方式來進行註冊,功能是相同的,你可以看到加等和減等是相當大的垃圾源,所以我們還是要考慮儘量避免他們的發生。
還有一點是我們有時候沒怎麼講到的是,就是說一個使用者介面的一些具體元素的效能,特別是玩家的HUD,因為玩家是用來理解遊戲世界遊戲中心的一些核心數值。最一開始的時候,螢幕頂部的一些小部件都是帶有Animator元件的使用者介面元素,這個問題是UI元件的移動,會導致我們的Canvas被標記為需要重新佈局,重新佈局,這對效能是有影響的,尤其是進行多處元件都在這樣做的時候。我們怎麼辦?我們乾脆移除了Animator,將UI元素例項化設定成靜態的狀態,並且使用著色器進行渲染,這樣相當於我們得到了動畫,但是我們的畫板還是非常乾淨的。如果在畫板上任何內容發生了變化,整個畫板都被標記使用過的或者是非乾淨的,並重新計算所需要的內容。所以將所有的靜態元素放到一個畫布上是最好的方法,將動態元素放到單獨的一個Canvas上也有用。對於單個元素的影響我們可以控制,我們重新組織了層級結構,因為大大提高了時間的效率。
另外一個就是效能優化就是一個定時器UI,一開始我們用一個整形計時,然後把整型轉換成字串,字串的建立會造成垃圾的產生和廢物的產生,我們通過預先分配的字串來,避免垃圾的產生。
其他的內容或者是更加具體的是我們的輸入是否有任何的延遲。那麼你可以看到Switch的版本最終實現的目標是每秒30幀,PC、XBox的目標是60,我們與其他版本相比,Switch的版本即使是在穩定情況下也是響應很慢的。通過調查我們發現兩個問題,遊戲移動系統以和遊戲相同的幀數進行,它是30幀或者是60幀,當玩家施加一個力,只是增加DeltaTime並不會實現同樣的結果,因為加速度和DeltaTime成正比,而速度不是,就意味著有一個物體在30的速度下加速變慢,我們必須把角色的更新頻率鎖定,使其以60FPS的速度執行,哪怕是在較低的幀速率下也是如此。即使做了這樣的調整,我們也是慢。我們使用高速的攝像機來錄製200FPS的視訊來進行測試。從我們輸入到它出現到螢幕上的時間,我們是拍攝螢幕和控制器,並且檢測到輸入後出現大白框的顯示,可以測量遊戲的輸入延時,那麼這個測試我們做了5次,同時計算了平均值。我們發現在遊戲中有一個與幀速率的延時,60PFS當中延遲的是一半,PS4是5幀,XboxOne是3幀,Switch是3幀,直接讀取本機的輸入,測試時間為PS4節省一些時間。最後我們將這些時間安排在一起,他們都來自於Unity,我們和Unity進行交談,看看我們有沒有方法來解決這樣一些問題。所以當你有機會做出這樣的變化時,儘早測試這個,特別是由於遊戲當中所產生的。
還有一個Split—Pad,其中有一個控制器,其中有半個控制器控制單個廚師,再使用另外一半控制另外一個角色二個控制。如果想讓兩個使用者互動,或者吵架的話,這種新的功能是對整個的環境是非常敏感的。你不能同時切菜和投擲,因為相同的按鈕不能用於兩個操作。
由於相容性問題,我們無法在聯機模式下使用Split-Pad,因為Split會導致建立一個新的Guest玩家,在聯網環境下,這個新的Guest玩家無法通過認證。但是我們確保了線上環境下可以用半個手柄來操作廚師的能力,它有一定的支援能力,那麼在往後看,並不是所有的這些主機都有相同的功能我必須要考慮到主機的一些差別。而且UI必須滿足這些不同主機的差異性,比如說我們在瘋狂廚師其他的特點,就是這種系統整合到主選單當中,而且選擇玩哪種模型之前,主人邀請朋友參與到他們的廚房活動中,這是非常好的系統,尤其是對於PS4和Xbox one和Steam來說,但是Switch上我們遇到了一個問題,因為這樣的功能並不是說所有的平臺都能支援的。我們需要在平臺上保持相同的體檢,所以就需要不同的使用者介面,這樣主機就可以進入線上的狀態,他們的朋友通過自定義選單來加入遊戲,我們需要另外一個自定義的程式碼路徑來支援瀏覽列表的概念,以支援附近的玩家加入進去。這樣的型別我們在下載的時候,有的時候都是在爭奪這一焦點,其中常見的例子是由於某些錯誤的狀態,如控制器斷開連結而出現的對話方塊,這些對話方塊的焦點,就是你要將它關掉焦點將丟失,所以我們要考慮到它的邏輯層。
由於我們是在主機上開發,我們還需要計劃一些不定和DLC作為其中的部分,在開發任天堂當中有時候需要AssetBundles的支援。同時平臺也要求你將Asset收集到Bundle當中,而不是將資源新增到場景當中。那麼在遊戲當中,我們建立了自動化的系統,將資源新增到一個固定大小的Bundles裡面,我們儘量調大這個閾值,這裡我們建立小的資源包,然後減少不定的範圍,或者是限定補丁的大小。我們使用了Asset Bundles,當你從裡面載入資料時,你的載入時間也會受到影響。
《胡鬧廚房》是非常棒的遊戲,也有很多人非常它,我們會不斷地優化我們的管線,尤其是關於它的細節,其中的一個挑戰就是我們希望能夠有更多的設定。
早期版本中,它使用了大量的半透明面片,讓美工可以控制,效能非常差。當遊戲釋出以後,我們釋出了特別建模的葉子,這提高了效能,也是讓遊戲有了風格。這樣一種單獨建立的樹上的葉子,也是比較好的改進,因為它更加適合我們的風格。
還有在最初的遊戲版本當中,幾乎每個遊戲物件都有自己的素材,還有一個簡單的著色器,完全滿足了物件在遊戲開發當中的需求,雖然這讓這個遊戲的開發變得更加簡單,這讓我們開始為每一個不同主題開始繪製它的紋理圖,並且貼合實際情況的著色器,每一層僅對所有的藝術資源使用很小的這樣一種素材,這隻用了1/4,所以提高了整體的幀速度,這是我們釋出以後最大的單效能提升,因此,我們的遊戲基本上都是以60秒/幀來運營。
我們已經為遊戲更新和釋出它的內容包,每個擴充套件包都有一個小型的活動,自從遊戲釋出以來,我們還新增了練習和生存的遊戲模式,玩家可以很放鬆地學習,並且知道每關怎樣玩。通過精心設計的元件系統,執行時可以切換網路元件和本地元件,無需對場景進行更改即可切換本地模式和聯機模式。這對補丁的大小來說也是很有幫助的,我們可以讓補丁非常小。
我的演講完了,謝謝!
相關文章
- 爆款小程式是如何誕生的?
- 遊戲設計淺析:玩《胡鬧廚房2》為什麼感覺不到時間流逝遊戲設計
- 功能遊戲爆款的誕生之路,《家國夢》背後的故事遊戲
- 《胡鬧廚房》的開發者告訴你,在遊戲行業怎樣當一名好廚師遊戲行業
- 《胡鬧廚房》開發商Team17上半年收入4千萬英鎊,再破自身紀錄
- Lisp的誕生Lisp
- 世界上第一款手機遊戲的誕生遊戲
- iDaily的誕生AI
- GlobalFoundries生產eMRAM解決方案
- 多平臺誕生爆款產品 文字劇情類小遊戲會是新風口嗎?遊戲
- 為什麼閒魚爆款突然不出單了?給你三個快速解決方案!
- Node Stream pipe的誕生
- 比特幣的誕生比特幣
- 廚房智慧監控系統訓練資料解決方案 | 景聯文科技
- 波卡生態現行的流動性解決方案
- 我們見證了兩款“王者榮耀”新遊戲的誕生!遊戲
- SAP 幾款容易令初學者混淆的 HANA 解決方案
- Web的誕生和網路基礎 | 讀《圖解HTTP》Web圖解HTTP
- 聊聊Seata分散式解決方案AT模式的實現原理分散式模式
- 程式的誕生到滅亡
- flutter 入門 - flutter的誕生Flutter
- Git 系列之「Git 的誕生」Git
- JavaScript是怎麼誕生的JavaScript
- 從二十年前誕生的一款“蠢遊戲”談起遊戲
- 煉成爆款小遊戲-首先解決傳播問題遊戲
- Python 執行js的2種解決方案PythonJS
- Redis哨兵模式高可用解決方案Redis模式
- SAP的這三款CRM解決方案,您能區分清楚麼
- 企業生鮮電商O2O平臺開發解決方案
- 用於巧克力生產的RFID完整解決方案
- Tomcat發生java.lang.OutOfMemoryError: PermGen space的解決方案TomcatJavaError
- 鴻翼雲生態大會之生態解決方案
- 安卓第五夜 維納斯的誕生安卓
- 網生代作家悄悄來襲 最經濟的創作-閱讀模式已經誕生模式
- 聖誕鬧劇!阿里旗下開源專案聖誕彩蛋遭開發者狂批阿里
- photoshop匯出png發生未知錯誤的解決方案,ps匯出發生未知錯誤怎麼解決
- 通用模板解決方案,提升影片生產效率
- NetSuite釋出首款統一的行業雲解決方案SuiteSuccessUI行業