如何重繪「江南百景圖」?近300頁 PPT 免費分享!
轉換 or 重寫
《江南百景圖》App 版遊戲包大小有 600+M,上線前期還有部分使用者反映遊戲執行時手機發熱嚴重。而小遊戲版在經過立項選型後,決定使用 Cocos Creator 重寫,僅用了1天就做出了 Demo。經過4個月的優化,我們最後將包體壓縮到 30M 左右,同時保證遊戲體驗與 App 版相當。
優化的過程中,我們也做了以下工作,其中 程式碼 部分需要重新設計和編寫。
渲染優化
原生版本的《江南百景圖》移植到小遊戲首先需要解決的就是 耗電高、易發燙、Draw Call 高等問題。
合批
合批是降低 Draw Call 最快也是最有效的方式。優化同樣的 Texture,將多張的圖片合併到一張圖集上,這樣不論要生成多少張不同的圖片,都不會打斷合批渲染,Draw Call 也就降低下來了。
但是《江南百景圖》的資源非常多,每個玩家使用資源的順序也不盡相同,如果玩家使用的資源分別在不同的圖集上,還是會導致合批渲染被打斷,產生 Draw Call。因此,針對這一情況,我們採用了 Multi-Texture 的方式進行了優化,其原理是將傳統的判斷是否在同一張圖集,轉換為判斷是否在 同一批圖集,這樣就大大減少了 Draw Call 產生。
另外,通過 gl.getParameter(gl.MAX_TEXTURE_IMAGE_UNITS) 這個指令,可以知道在一臺裝置中 Shader 最多支援幾張圖集。測試發現目前 90% 以上的手機至少支援8張,因此我們將批圖集的數量設定為8張。因為一個批次有 8 張圖集,所以我們是通過這個 idx 判斷某張圖用的哪個圖集,程式碼也很簡單。
動態合圖
小遊戲版本採用了 Cocos 的動態合圖機制,這樣在 CDN 下載的圖片也能進行合圖。而為了提高合圖的效率,避免浪費空間,我們會將長度或者寬度特別大的圖片進行裁剪。
例如左圖中的旗杆,由於圖片太長,在動態合圖時會導致空間浪費,因此我們將這張旗杆的圖片裁剪成兩張,如右圖所示,再在專案中進行拼接處理。
採用同一個材質資源
在《江南百景圖》中,玩家移動地圖時,原本在顯示範圍外的圖片將從水墨色變為彩色。
傳統的方案是改變圖片材質,當地圖移動到要顯示的節點時,節點一個一個地進行材質的切換,達到一個 “淡入淡出” 的效果。但是在專案中嘗試之後,我們發現這樣會導致 Draw Call 上升,而且拖拽地圖又是一個很頻繁的操作,遊戲中實際效果較差。
因此在這裡我們將所有城市物體資源,無論是人物還是建築、常態還是淡入狀態,都用統一的 Material、並使用頂點資料傳遞“時間引數”,以此節約效能消耗,最終達到所有建築和人物的建立、移動、銷燬等全都只需要一個材質就能夠完成。
很多人會覺得一個普通的圖片也用這麼複雜的方案,會影響效能,導致效能變差。但是實際測試效果並不差,這也告訴我們,在遊戲開發中還是要以實踐為準,不能想當然。
優化 Shader 的輸入資料
由於《江南百景圖》的圖片資源中不會用到 Color 這個屬性,因此在材質中,我們將原有的 Color 資料去除掉。
下圖是一個正常的頂點資料:
接下來將原有的 Color 資料去除掉,用來存放專案中所需要的其它資訊,這樣可以減少 CPU 與 GPU 互相傳輸的資料量。
層級規劃
我們將不同的型別的資源,分別放置在對應的層級中。《江南百景圖》共分了13個層級,下圖只展示了部分比較重要的層級:
其中比較有意思的是旗幟層。旗幟是《江南百景圖》中的一個常見元素,但因為專案實際技術限制,無法將一個旗幟製作在一個完整龍骨動畫中,如果強行放在一起,就會導致在渲染到旗幟的時候出現斷批。我們採用了 動態組織層級關係 的方式來解決這個問題。例如這是一個原來的旗幟預製體:
採用 動態組織層級關係 的方式,將旗杆與旗面拆開,旗杆放在下面的普通建築物層,旗面則單獨分為一層旗幟層放在上層,這樣就很好地避免了渲染時一直被打斷合批的情況。
UI 渲染優化
UI 部分我們沒有使用動態合圖或者 MultiTexture,動態合圖我們留給了遊戲中的人物和建築、而沒有使用 MultiTexture 主要是開發成本的原因。但在我們的優化下,現在遊戲的 Draw Call 可以降得很低。
UI 方面我們也是做了分層,比如下面左邊的圖上我們的 button 層,裡面都是按鈕部分,右邊是我們的標籤牌層級。這樣我們就可以根據功能區去劃分圖集,然後和遊戲裡的層級對應起來,而不會打斷合批。
自定義引擎
Cocos 是個開源引擎,我們可以根據專案的實際需要,對引擎進行定製、修改,從而達到更好的效果。
增強 TiledMap
我們在 Cocos Creator 原有的 TiledMap 元件的基礎上,擴充了新的功能,下圖是 Cocos 自帶的元件。
這裡就不詳細說了,有興趣的可以去官方文件查閱,我們主要來說一下經過擴充的新功能。
1. Diamond Tile:遊戲中使用了很多 TiledMap 中的圖塊菱形方塊, 但是引擎預設的傳遞方式是矩形,這樣就會造成資料浪費和冗餘。
這些圖片首先都是 規則的菱形,所以很簡單,直接 根據寬高進行進行計算。
將菱形周圍多餘的部分切割,這樣很明顯圖片大小減少了一半,這裡注意一下非標準圖形就不能這麼用了。
2. Share Culling:《江南百景圖》共有三層 TiledMap 地圖層,勾選時 將只對 TiledMap 的第一個地圖層進行處理判斷可視區域的範圍,而其他的地圖層將直接照搬第一個地圖層的處理結果,這樣能夠節約不少效能。
3. With Color:如果不需要顏色資料就可以勾選,減少資料量的傳輸。
將道路轉為 Tile
遊戲中的道路是不需要進行淡入淡出效果的,如果當作普通建築物資源來用之前的材質進行渲染,會消耗相當多的效能。因此我們將道路作為 Tile Map 地圖的一部分,讓道路不需要用之前提到的材質進行渲染。
還有一個小細節,在 Tiled Map Editor 中設定的寬高,與實際專案中使用是無關的,因此在生成的時候可以將地圖塊按照實際專案需求進行縮小,減少資源使用。
資源壓縮
將一個原版 600+M 的遊戲壓縮到最終的 30M 左右,資源的壓縮工作必不可少。我們需要將遊戲資源進行合理的壓縮,使其更加適合小遊戲執行,並且不影響遊戲最終的顯示效果。
圖片縮放
對不同型別、不同清晰度的資源,我們可以設定不同的縮放比例。我們將大部分的建築縮放到原來的 0.65 倍,背景中的山川則被縮放到原來的 0.3 倍。另外,就算是相同位置上使用的人物立繪,由於每個人物的自身和背景的顏色、精度不同,也都可以給它們設定不同的縮放比例。
於是我們將所有 Sprite 元件採用 Custom 模式,可以自由控制比例。不同的圖片使用差異化配置,設定不同的縮放比例,用指令碼控制縮放比例,這樣便可以打包出任意畫質和體積的各種版本,並且還提升了動態合圖的利用率和部分效能。
圖片減色
綜合比較了大家比較熟知的 tinypng 和 pngquant 兩種工具之後,專案最終選擇使用 pngquant 對 PNG 圖片進行批量壓縮。pngquant 可以自定義壓縮品質,而且 pngquant 開源,容易維護,風險可控。pngquant 也提供像 ImageAlpha 這樣的工具,可以實時檢視圖片減色後的效果,方便調整引數。
pngquant 地址:
https://pngquant.org/
需要注意的是,由於 Cocos 會進行合圖處理,如果對 Build 前的圖片做壓縮,合圖時前期的一些壓縮工作可能就此無效化,所以我們要對 Build 後的圖片 做壓縮處理。
另外我們也建議程式多瞭解一下圖片格式以及其原理。不是所有圖片都要使用 PNG 格式,也會有使用 JPG 的情況。
場景剔除
這部分我們的需求是 只渲染可視物體。那麼用什麼方法確定哪些物體是可見的呢?最開始我們使用了四叉樹,但是在 JS 語言中的效果並不好。所以我們給地圖劃分格子,Grid 的單元格大小要適中,但單元格的邊長應為 2的整次冪,便於利用 位運算 提升效能。
如下圖所示,紅框就是鏡頭,所以需要渲染的也就是這個紅框裡出現的格子。然後我們再根據建築物的座標、大小去進行計算,判斷建築在哪一行哪一列的格子裡,從而確定該建築物是否是需要被渲染的物體。
這是一段簡單的檢測函式 大家可以根據自己的專案需求去進行擴充套件。
除此之外,為了防止特殊情況出現,判斷的可視範圍需要比實際範圍更大一些。
尋路
《江南百景圖》使用的尋路演算法,有針對單源單點的 A* 和單源多點的 Dijkstra。但這裡我們要講的不是尋路演算法,而是在遊戲中的用法優化。
針對地圖很大、建築物和人物都很多的情況下,這些演算法一起執行就會很損耗效能。所以我們用了 分時尋路,就是把尋路過程由一幀分到若干幀去進行計算,這樣就不會在某一個時間段集中進行大量運算,對遊戲效能也不會有太大的影響。
除此之外我們還在遊戲裡做了一個大膽的優化,就是統一管理尋路任務,同一時間只為一個角色服務。也許有人會問,那豈不是一個角色在哪裡走、其他物件都在那邊等著?其實真正在遊戲裡不會有這種奇怪的表現。首先每個角色尋路的起始和結束時間都不一樣,再者這個同一時間是非常短的,就等於把角色尋路分配到了不同幀裡,交替進行執行。
再談效能
模糊特效
玩家在開啟《江南百景圖》的任意介面時,遊戲的背景需要做模糊處理,而背景中的人物動畫等仍需要正常播放。
在經過一系列的研究(可參考 PPT 中資料)後,我們選擇了一個較好的方案,將場景渲染到一個小的 RenderTexture 上,然後將其通過 Kawase 模糊後再放大 顯示,如下圖所示。
RenderTexture 池
在小遊戲或 Web 端 建立 RenderTexture 時,比較損耗效能。所以我們在遊戲中使用完 RenderTexture 後,不是直接銷燬,而是將其放在一個 快取池 中,下次從快取池中呼叫符合要求的 RenderTexture 即可。
點選檢測
《江南百景圖》中有很多建築物,而在使用者點選時,並非簡單地通過地形上的塊做判斷,而是給每個建築物畫了一個 多邊形檢測區域。但是建築物是移動的,如果 多邊形檢測區域 也隨之移動,從效能和邏輯上都不是好的處理方式。
於是在實際操作中,我們讓建築物移動,而對應的 多邊形檢測區域 不做移動,並將其設定在原點座標上。使用者點選操作時,將點選的座標減去建築物相對原點的座標,就可以進行點選檢測了。同理如果建築物是反轉狀態,可以將點選座標進行映象,而 多邊形檢測區域 仍然可以不做調整。類似還有其他情況,大家也可以去了解一下各情況下對多邊形的處理方式。
陣列排序
陣列排序是大家容易忽略的一個優化模組,Array.sort() 這樣的 快速排序 演算法,更適用於混亂無章的資料。而在《江南百景圖》中,每幀都會對場景中的人物和建築物進行排序,而連續的兩幀之間差異不會很大,也就是 相對有序 的資料,而這更適合使用 插入排序 演算法。
其他優化
「閱後即焚」
遊戲中存在一些低頻顯示的大圖,例如進入遊戲時的公告、抽到的卡片等,玩家在遊戲中看一遍就不會再出現了,對於這一類我們用了“閱後即焚”的思路。
像這些大圖,我們通常先從遠端伺服器下載到本地快取,產生 Image 物件,還有cc.Texture2D、renderer.Texture2D。
我們通過虛擬碼來簡單講解一下。載入圖片時,將圖片新增到我們自己建立的回收用工具類 TextureRecycle 中。
檢視關閉時,通過工具類回收這些圖片。
在圖片的回收階段中,就可以將以上所有用到的物件都清理乾淨了。
構建優化
在構建釋出流程中,專案使用了大量的自動化指令碼來優化構建流程。包括 全平臺構建、上傳遊戲平臺、資源預處理和後處理、CDN 同步和版本控制和二次混淆加密 等。但成也指令碼敗也指令碼,過長的構建時間也造成了不少困擾,因此我們也需要做一些額外優化。
Cocos 新版本新增了一個第三方開源壓縮工具 Sharp,壓縮級別是0-9,數值越大壓縮越久,Cocos 的預設引數是 6。由於我們已經進行過 圖片減色 處理,因此我們將引數改為 0,這樣就能減少很多構建的時間。
而各平臺構建時間總是格外漫長,原因是在每次平臺構建時,Creator 都要重新生成對應的平臺圖集。找到原因後,我們在每次構建前,將對應目錄中的 info.json 中的 actualPlatform 引數先修改為 對應的平臺名稱 再打包,這個改動使我們的構建時間由之前的 15 分鐘縮短到 10 分鐘左右,提升了 30% 效率。
在不懈的優化下,我們看到在現場演示時,這個用於官方演示遊戲的高階賬號,在遊戲場景人物都很豐富的情況下,仍然只有 6個 Draw Call。
來源: COCOS
原文:https://mp.weixin.qq.com/s/4s-xK0pAP972tDxJ3VchqA
相關文章
- 如何免費將PDF轉成PPT?
- flutter實戰6:TAB頁面切換免重繪Flutter
- 免費404頁面程式碼分享 404錯誤頁面原始碼原始碼
- 如何免費將PDF轉成HTML網頁?HTML網頁
- 可免費使用的免費API分享API
- 免費api介面大全分享API
- nb!免費api大全分享API
- 免費api分享,趕緊收藏~API
- 各類免費好用API分享API
- 免費好物API分享大全API
- 免費分享海量詳情頁模板,無需下載線上設計!
- 分享20套精美的免費分頁按鈕 PSD 原始檔
- 網頁效能管理:重繪和重排網頁
- 開源免費繪畫軟體 - Krita for MacMac
- AI繪畫軟體免費嗎?有哪些免費的ai作畫平臺!AI
- 分享5款Mac免費軟體Mac
- 開發者福利:好用免費的API分享API
- 免費的網頁截圖API網頁API
- 快速繪畫應用:Growly Draw for mac 免費版Mac
- 茶葉類詳情頁設計素材免費分享,線上就能預覽使用!
- 免費的論文查重網站網站
- 免費國外ip代理地址分享
- 牆裂分享的免費好用api介面API
- 有意思、好用的免費API分享API
- 一波好用、免費api介面分享API
- 分享我免費可用API介面網站API網站
- 寶藏API:免費好用的api分享API
- 分享收藏的熱門免費api介面API
- 愛心樹表白動畫原始碼——免費分享動畫原始碼
- 【資源分享】各類免費API大全API
- 今日免費分享直通車主圖模板,免排版直接用!
- 免費,一鍵釋出web頁面Web
- 分享(三):超全品類的免費可用 API 彙總(含AI 繪畫,持續更新中)APIAI
- 免費WiFi真免費?蹭網後自家無線密碼也被分享了WiFi密碼
- 如何識別網頁上的文字?線上工具免費識別網頁
- 網店開設教程免費分享,無套路乾貨分享!
- 分享免費下載論文的網站網站
- 業餘草分享大量IT資料免費領!