<tbody id="suqa6"></tbody>
  • <acronym id="suqa6"><kbd id="suqa6"></kbd></acronym>
    <acronym id="suqa6"></acronym>
  • 微信公開課小游戲專場 | 游戲設計與性能優化分享

    ?8 月 19 日,第九季微信公開課小游戲專場在廣州舉辦,這也是本年度第一場線下微信公開課?;?Cocos 引擎研發的《最強魔斗士》《英雄殺》《胡萊三國》《山海經異變》等熱門游戲 CP 亮相公開課現場并帶來了關于小游戲性能調優、廣告變現及內購玩法的實戰經驗與“避坑指南”。其中,來自騰訊光子歡樂工作室的前端主程譚家章就《最強魔斗士》項目分享了小游戲性能優化經驗,以幫助更多開發者制作出更加高品質的小游戲。

    以下為直播演講文字整理,字字干貨,歡迎閱讀!

    大家好!我們今年上線了一款 2.5D 小游戲《最強魔斗士》,今天我主要分享一下這款游戲的技術設計以及性能優化經驗。

    先來簡單介紹一下我們的游戲,《最強魔斗士》核心玩法是彈幕射擊類,大地圖采用斜 45 度視角的。今天主要做的是技術分享,所以我先說明一下我們的技術規格:

    《最強魔斗士》是一款微信小游戲,使用的引擎是 Cocos Creator 3D。為了人物動作的流暢,游戲的主角和怪物使用了 3D 模型。此外,游戲采用固定視角,主要是便于 2D 跟 3D 相結合的表現。從性能角度考慮,其實我們更偏重于 2D 渲染,除了人物跟怪物以外,我們其他的元素比如地表、金幣、子彈還有光效、陰影這些都是用 2D 渲染的。

    技術方面有一點值得關注的就是,目前小游戲在蘋果下面的性能瓶頸是很突出的,主要是 CPU 端性能。更具體地說,其實就是 JS 運算效率不足。另外,我們游戲本身也比較復雜,戰斗邏輯復雜,同屏模型數量、2D 精靈數量都非常多,所以我們把支持的最低端設備的定為蘋果 iPhone6s,后續提到的性能相關數據,也是基于這個設備來測量的。

    今天我將分享三個方面的內容:

    一、戰斗方面的基礎設計

    • 戰斗場景層級劃分
    • 人物和怪物模型的渲染

    二、針對幀率以及幀率的穩定性所做的針對性優化方案

    • 地表的實現和渲染優化
    • 節點矩陣運算簡化
    • 節點增刪性能的優化

    三、瓶頸分析手段及后續思考


    一、戰斗方面的基礎設計

    1、戰斗場景層級劃分

    先看一下我們的場景層級劃分,層級劃分主要有兩個目標:一是更好地把 2D 跟 3D 元素相結合,二就是傳統的 Drawcall 優化。

    從圖片中可以看到,我們把最頂層的節點劃分為了遠景層、近景城還有地表層,在地表層之上的又放著人物跟怪物的 3D 層,然后 3D 層的上下兩邊就各自放了兩個動態的 2D 精靈層,動態的 2D 精靈層又細分為陰影、子彈、數字還有光效等等小層級。

    劃分之后,我們約束每個小層級只能用一張紋理圖集。這樣引擎在渲染小層級的時候,就可以動態地把里面所有的精靈合成一個 Drawcall 來渲染,就能夠比較好地控制 Drawcall。

    目前我們 Drawcall 控制在四十以下,算是一個比較小的值,不過 Drawcall 控制地小不意味著性能就很高,因為這只是其中的一個必要的優化。

    2、人物和怪物模型的渲染

    然后來看一下我們在 3D 模型渲染方面的一些設定:

    我們的 3D 模型主要用在主角和怪物的骨骼動畫,這里最關鍵的兩項優化技術就是 GPU 蒙皮和 BakedAnimation。

    GPU 蒙皮比較常用,它把復雜和耗時的頂點蒙皮從 CPU 轉移到 GPU層;BakedAnimation 是動畫系統的一種緩存策略,它把關鍵幀緩存起來以后,后面每幀只要去渲染就可以了,不用反復地計算。

    這兩項優化手段共同點都是以降低 CPU 運算為目標,而小游戲目前的瓶頸就在 CPU 這一側,他們的優化效果是比較好的。

    解決了單個骨骼動畫的渲染問題后,還要處理當同屏數量很大的情況。

    從圖片中也可以看到,我們有些復雜場景是存在同時有數十個模型同屏的情況的,這個時候,就要啟用 GPU Instancing 技術的優化了,它可以用一個 Drawcall 來渲染多個重復模型,這樣就可以使得 CPU 端的 Drawcall 和消耗都控制得比較低,它不會隨著模型數量的遞增而線性的增長。

    要說明的是,以上優化手段,其實 Cocos Creator 3D v1.1.0 以上版本都已經支持了。

    另外,我們還關閉了實時陰影,采用 2D 精靈來模擬的方式。經過上述的一些設定之后,目前我們在戰斗里面的模型渲染耗時大概是 7ms 左右,屬于一個可接受的范圍。

    二、一些針對性的優化方案

    1、地表的實現和渲染優化

    然后來看下我們的地圖,我們用小圖塊拼接的大地圖,它的優勢就是紋理復用,可以節省下載量和內存占用。

    為了支持地圖的快速編輯,我們開發了專門的編輯器,可以看到不管這個地圖最終編輯成多大,最終輸出的資源都是一張圖集,這樣可以比較好地控制我們 Drawcall 數量。

    小圖塊拼接有什么問題呢?主要問題就是當圖塊數量很多的時候,渲染壓力會非常大。在《最強魔斗士》中,把場景外的節點剔除以后,同屏圖塊數量還是達到 300 個以上,如果用常規的渲染方式去渲染的話,渲染耗時會達到 6ms 以上,這是無法接受的。

    這么耗時的原因在于做渲染的時候要做動態合批,需要遍歷所有的精靈節點,然后計算它們的頂點、UV、IBuff、Color 等數據,合成一個 batch 來提交渲染,這么做雖然 Drawcall 很低,但是 CPU 側的運算量依然很大。

    根據地圖塊固定不變的特點,我們聯想到可以用靜態合批的方式來優化。靜態合批的優勢其實就是把上述提到的動態合批的渲染過程,把它給緩存下來,然后后續每幀就不用去計算,只需要提交渲染就可以了,具體的實現引擎也有相關的組件可以比較好的支持。

    經過了靜態合批之后呢,我們的地表渲染耗時從 6ms 下降到 1ms 以下。

    2、節點矩陣預運算簡化

    除了前面說的靜態的地圖塊之外,我們場景里面還有大量的動態節點,比如說截圖里面看到的一些子彈、光效、血條、陰影等等,它們的數量非常大,會有 100 個以上,每個 2D 精靈本身是處在一定的容器結構里面,所以場景里面實際上在運動的節點比我們看到的精靈數量還要多很多。

    經過我們的統計發現,最復雜的關卡里面會同時存在 600 個以上的節點,節點數量這么大的會存在什么問題呢?最主要一點就是節點的矩陣運算會耗時比較多。

    Cocos 引擎節點是通過矩陣來計算變換的,這也是一種最通用的實現方式。優勢是可以完整地支持平移縮放還有旋轉,劣勢就是比較復雜,尤其是在 JS 上面去計算。

    這么大量的矩陣運算有沒有辦法去優化呢?這里有一個關鍵點就是其實場景里面的大部分節點,并不需要支持旋轉,而是僅僅需要做位移跟縮放就好了,旋轉就是矩陣運算里面最復雜的一塊。

    所以呢,我們從這里就會看到一個可優化的點,我們的做法是這樣子:基于前面的假設去修改了引擎在計算節點變換的邏輯,把計算位置這塊的矩陣運算給去掉了,換成了一個簡單的求和跟乘積運算,這樣就能支持位移和縮放,也能算出節點的最終位置。

    這項優化對于場景里面的 80% 節點都是有效的,所以帶來效果也比較好,在復雜關卡里面的話可以有一到兩毫秒的耗時下降。

    3、節點增刪性能的優化

    前面提到節點數量很大,節點數量很大除了矩陣運算消耗以外呢,還有一個不太容易關注到的節點增刪性能問題。

    在 Cocos 節點樹設計上,節點增刪是有一定的性能消耗成本的,當同時增刪的節點數很大的時候,這個成本就非常突出了。

    《最強魔斗士》又是一款彈幕類游戲,節點數量增刪特別頻繁,比如說某些時刻我們會有幾十個子彈創建,同時又有幾十個子彈在消失,同時還伴隨著數十個特效、陰影的創建和消失,統計發現復雜關卡里一幀最多會發生 200 次以上的節點增刪。那么這個節點增刪他帶來的運算峰值就足以帶來幀率的驟降,給用戶帶來卡頓的體驗。

    節點增刪不是一種持續性的消耗,所以在平均幀率上面的體現不明顯,所以因為這樣而容易被忽略。

    我們怎么優化這個問題呢?我們采用的方式就是懶增刪的方式。就是一旦節點被添加到節點數之后,我們就不再移除它。當我們要隱藏的節點時,我們用一個輕量級的方法來替代引擎的接口,比如往節點里面設置一個隱藏屬性,然后修改一下引擎的渲染流程。當遇到這些隱藏節點時候呢,我們就跳過他,這樣就可以實現節點的隱藏。

    這樣修改以后呢,我們的節點增刪就基本上沒有多少消耗,也不會產生預算峰值和卡頓。

    三、瓶頸分析手段及未來思考

    最后,分享一下我們的瓶頸分析手段以及一些未來思考。

    首先性能優化,我們的重點對象其實是蘋果設備,然后蘋果設備上面的目前是沒法做真機 Profile的,所以這正好給我們帶來一些挑戰。

    蘋果怎么做幀率優化呢?我這里推薦一個土方法吧,我們在引擎的主循環或者我們邏輯主入口里面去做一些耗時統計,這算得是個大循環的總耗時。然后運行過程中的我們動態去開關一些節點和功能,然后通過總耗時的變化發算出子系統的自身耗時。

    這個方法的優勢就是簡單,它對于一些粗粒度的性能消耗統計是準確的,缺點也很明顯就是他無法做更細粒度分析,比如說無法定位到具體函數。

    另外也可以在 PC 和安卓上面做 Profile,有時候也可以在定位出一些運算熱點。不過在 PC 上面做 Profile 的話,它反映出來的熱點分布跟蘋果上面是不完全一致的,所以這里要注意不要被誤導。

    這是我們做的一些工具:

    左邊的是節點管理工具,它可以在運行的時候展示整個場景當前的所有節點,然后可以去動態地禁用和激活節點,主要是用來評估某一類節點的渲染耗時,比如說骨骼動畫的耗時。

    右邊是些 GM 工具,可以開關一些我們的業務邏輯,比如說把碰撞關閉、把怪物行為暫停。

    經過上述的分析,我們可以得到整個游戲的一個耗時分布圖。

    可以看到,經過一輪優化之后呢,目前耗時大頭就是模型渲染跟戰斗邏輯這兩塊,總耗時達到了 25 毫秒,所以在蘋果 6s 上面只能跑到四十幀左右。

    后續如何進一步優化呢?我想除了需要有更好的方案以外,可能也需要蘋果就是平臺側提供些更精細的優化工具,否則我們的瓶頸分析效率非常低。

    后續還有比較值得關注的一點就是可以利用 Worker 線程來緩解主線程的壓力,我們目前在做一個事情就是把我們的戰斗邏輯給整體遷移到 Worker 去。

    從圖里可以看到,假設我們完成了這項遷移的話呢,我們的主線程消耗是可以大大降低的, 有28%左右。但這里還需要平衡的這個邏輯的遷移成本和 Worker 本身的通信成本。

    以上就是我今天的分享。

    謝謝大家!


    《最強魔斗士》相關分享:

    国产亚洲精品视觉盛宴,日韩 精品 综合 丝袜 制服,一个添下面两个吃奶把腿扒开,国产真实露脸乱子伦