化實(shí)戰(zhàn):從Draw Call到內(nèi)存管理的全鏈路指南)
1. 項(xiàng)目概述為什么Cocos Creator性能優(yōu)化是開(kāi)發(fā)者的必修課做游戲開(kāi)發(fā)尤其是面向移動(dòng)端性能優(yōu)化這個(gè)話題就像懸在頭頂?shù)倪_(dá)摩克利斯之劍。你可能花了幾周時(shí)間精心打磨出一個(gè)玩法有趣、畫(huà)面精美的Demo結(jié)果一上真機(jī)幀率直接掉到20以下手機(jī)燙得能煎雞蛋玩家體驗(yàn)瞬間歸零。這不是危言聳聽(tīng)而是很多新手甚至老手都踩過(guò)的坑。今天我們就來(lái)深入聊聊Cocos Creator引擎開(kāi)發(fā)中的性能優(yōu)化這不僅僅是第18課的內(nèi)容更是貫穿你整個(gè)開(kāi)發(fā)周期的核心生存技能。Cocos Creator作為一款流行的跨平臺(tái)游戲引擎其易用性和強(qiáng)大的編輯器功能吸引了大量開(kāi)發(fā)者。但“開(kāi)箱即用”的便利背后也隱藏著性能陷阱。引擎幫你處理了渲染、物理、邏輯更新等復(fù)雜事務(wù)但如何高效地使用這些能力避免資源浪費(fèi)和性能瓶頸責(zé)任完全在開(kāi)發(fā)者肩上。性能優(yōu)化不是項(xiàng)目尾聲的“選修加分項(xiàng)”而是從項(xiàng)目立項(xiàng)、資源規(guī)范、代碼架構(gòu)設(shè)計(jì)之初就必須考慮的“基礎(chǔ)建設(shè)”。它關(guān)乎你的游戲能否在千元機(jī)到旗艦機(jī)的廣闊設(shè)備譜系上流暢運(yùn)行直接決定了產(chǎn)品的留存率和口碑。2. 性能優(yōu)化的核心思路從“二八原則”到“數(shù)據(jù)驅(qū)動(dòng)”在動(dòng)手優(yōu)化之前我們必須建立正確的優(yōu)化觀。盲目地、過(guò)早地進(jìn)行“優(yōu)化”往往是浪費(fèi)時(shí)間的根源。這里需要引入兩個(gè)黃金法則。2.1 理解并應(yīng)用“二八原則”與“夠用原則”網(wǎng)絡(luò)資料中提到的“二八原則”是性能優(yōu)化的第一性原理系統(tǒng)中20%的代碼會(huì)消耗80%的性能。這意味著我們的優(yōu)化火力必須精準(zhǔn)不能遍地撒網(wǎng)。在Cocos Creator項(xiàng)目中這20%通常集中在幾個(gè)關(guān)鍵區(qū)域渲染尤其是Draw Call、UI復(fù)雜度、物理計(jì)算、頻繁的JavaScript邏輯如update中的復(fù)雜運(yùn)算、以及資源加載。緊隨其后的“夠用原則”則是一種務(wù)實(shí)的美學(xué)。它要求我們?cè)谛Ч托阅苤g找到平衡點(diǎn)。例如一個(gè)背景UI元素使用RGBA4444格式的紋理與RGBA8888格式在大多數(shù)手機(jī)屏幕上肉眼幾乎無(wú)法分辨差異但前者能節(jié)省一半的紋理內(nèi)存和帶寬。音頻文件也是如此對(duì)于背景音樂(lè)44.1kHz的采樣率可能就足夠了無(wú)需盲目追求96kHz的高保真后者會(huì)顯著增加包體和內(nèi)存占用。這個(gè)原則的本質(zhì)是在滿足美術(shù)和策劃需求的最低質(zhì)量標(biāo)準(zhǔn)下選擇性能開(kāi)銷(xiāo)最小的方案。2.2 建立“數(shù)據(jù)驅(qū)動(dòng)”的優(yōu)化流程從猜想到實(shí)證很多開(kāi)發(fā)者優(yōu)化性能靠“猜”和“感覺(jué)”這是最要命的。性能優(yōu)化必須是一個(gè)“數(shù)據(jù)驅(qū)動(dòng)”的科學(xué)過(guò)程。流程應(yīng)該是發(fā)現(xiàn)卡頓 - 使用工具定位瓶頸 - 針對(duì)性優(yōu)化 - 驗(yàn)證效果。發(fā)現(xiàn)卡頓不要只在高配開(kāi)發(fā)機(jī)上測(cè)試。必須準(zhǔn)備多款中低端真機(jī)進(jìn)行測(cè)試感受幀率波動(dòng)、操作響應(yīng)延遲和發(fā)熱情況。Cocos Creator編輯器自帶的預(yù)覽模式性能面板和構(gòu)建后的調(diào)試模式是第一步。定位瓶頸這是最關(guān)鍵的一步。你需要工具告訴你是CPU忙還是GPU忙如果是CPU忙是腳本邏輯JS耗時(shí)多還是引擎底層如渲染提交、物理計(jì)算耗時(shí)多如果是GPU忙是填充率過(guò)度繪制問(wèn)題還是頂點(diǎn)處理問(wèn)題針對(duì)性優(yōu)化根據(jù)定位到的瓶頸采取對(duì)應(yīng)的優(yōu)化策略。比如CPU的Draw Call高就合并渲染批次GPU過(guò)度繪制嚴(yán)重就優(yōu)化UI層級(jí)和裁剪。驗(yàn)證效果優(yōu)化后再次使用工具測(cè)試用數(shù)據(jù)對(duì)比優(yōu)化前后的差異確保改動(dòng)是正向的且沒(méi)有引入新的問(wèn)題如畫(huà)面錯(cuò)誤。3. CPU側(cè)性能優(yōu)化實(shí)戰(zhàn)向每一毫秒要效率在移動(dòng)設(shè)備上CPU往往是第一個(gè)瓶頸。Cocos Creator的JavaScript邏輯運(yùn)行、渲染命令的提交構(gòu)建渲染數(shù)據(jù)都在CPU上完成。3.1 渲染優(yōu)化的基石理解與降低Draw CallDraw Call繪制調(diào)用是CPU向GPU發(fā)起的一次繪制命令。每一次Draw CallCPU都需要準(zhǔn)備數(shù)據(jù)、設(shè)置渲染狀態(tài)這是一個(gè)相對(duì)耗時(shí)的操作。網(wǎng)絡(luò)資料中建議“盡量保持繪制調(diào)用次數(shù)低于50”這是一個(gè)非常實(shí)用的經(jīng)驗(yàn)值。對(duì)于復(fù)雜的2D游戲或輕量3D場(chǎng)景超過(guò)這個(gè)數(shù)CPU就可能不堪重負(fù)。如何降低Draw Call自動(dòng)合圖Auto Atlas與靜態(tài)合圖Static Atlas這是最有效的手段。Cocos Creator的自動(dòng)合圖功能會(huì)自動(dòng)將散圖打包成一張大圖集。確保在項(xiàng)目設(shè)置的“項(xiàng)目數(shù)據(jù)”-“自動(dòng)圖集”中啟用并合理配置。對(duì)于UI常用圖標(biāo)可以手動(dòng)制作靜態(tài)合圖確保它們?cè)谕粡埣y理中。動(dòng)態(tài)合批Dynamic Batching引擎會(huì)自動(dòng)嘗試將使用相同材質(zhì)和紋理的多個(gè)Sprite精靈在同一個(gè)Draw Call中繪制。但合批有嚴(yán)格條件相同紋理、相同混合模式、非自定義材質(zhì)等。在UI中盡量讓相同圖集的元素在節(jié)點(diǎn)樹(shù)結(jié)構(gòu)上相鄰有助于提高合批成功率。減少材質(zhì)變體每個(gè)不同的材質(zhì)Material實(shí)例都會(huì)打斷合批。避免為大量相同精靈創(chuàng)建微調(diào)了某個(gè)參數(shù)的材質(zhì)實(shí)例。如果只是調(diào)整顏色優(yōu)先使用Sprite組件的color屬性它不會(huì)打斷合批。UI組件的優(yōu)化Label文本組件是Draw Call大戶。特別是使用系統(tǒng)字體TTF時(shí)每個(gè)Label可能都是一個(gè)獨(dú)立的Draw Call。對(duì)于頻繁更新且樣式固定的文本如分?jǐn)?shù)、金幣數(shù)務(wù)必使用BMFont位圖字體。BMFont將字體預(yù)渲染為紋理渲染效率極高是游戲內(nèi)動(dòng)態(tài)文本的首選。實(shí)操心得我曾在一個(gè)卡牌游戲項(xiàng)目中發(fā)現(xiàn)戰(zhàn)斗場(chǎng)景Draw Call高達(dá)120。使用性能分析工具逐幀查看發(fā)現(xiàn)罪魁禍?zhǔn)资菐资畟€(gè)使用了不同字號(hào)和顏色的TTF Label。將它們?nèi)刻鎿Q為精心制作的BMFont后Draw Call直接降到35以下幀率從40fps恢復(fù)到滿幀60fps效果立竿見(jiàn)影。3.2 邏輯代碼的性能陷阱與規(guī)避JavaScript邏輯的性能同樣至關(guān)重要特別是在update、lateUpdate這些每幀執(zhí)行的函數(shù)里。避免在循環(huán)中執(zhí)行昂貴操作查找節(jié)點(diǎn)絕對(duì)不要在update里使用this.node.parent.getChildByName(“xxx”)或find方法。應(yīng)該在start或onEnable時(shí)緩存引用。創(chuàng)建/銷(xiāo)毀對(duì)象頻繁的instantiate實(shí)例化和destroy銷(xiāo)毀會(huì)觸發(fā)垃圾回收GC導(dǎo)致幀率卡頓。對(duì)于子彈、特效等需要頻繁生成的對(duì)象必須使用對(duì)象池Object Pool。Cocos Creator提供了cc.NodePool務(wù)必掌握。// 對(duì)象池使用示例 import { _decorator, Component, Node, NodePool, Prefab } from cc; const { ccclass, property } _decorator; ccclass(BulletManager) export class BulletManager extends Component { property(Prefab) bulletPrefab: Prefab null!; private _bulletPool: NodePool new NodePool(); start() { // 初始化對(duì)象池預(yù)創(chuàng)建一些對(duì)象 for (let i 0; i 20; i) { let bullet cc.instantiate(this.bulletPrefab); this._bulletPool.put(bullet); } } spawnBullet(pos: Vec3) { let bullet: Node null; if (this._bulletPool.size() 0) { bullet this._bulletPool.get(); } else { bullet cc.instantiate(this.bulletPrefab); } bullet.setParent(this.node); bullet.setPosition(pos); bullet.getComponent(Bullet).init(); // 重置子彈狀態(tài) return bullet; } recycleBullet(bullet: Node) { bullet.removeFromParent(); this._bulletPool.put(bullet); // 回收到池中而非銷(xiāo)毀 } }減少不必要的計(jì)算與判斷例如距離判斷可以先比較距離的平方避免開(kāi)方運(yùn)算。對(duì)于不常變化的值計(jì)算一次后緩存起來(lái)。善用“啟用/禁用”而非“創(chuàng)建/銷(xiāo)毀”對(duì)于UI面板、常駐特效等如果只是暫時(shí)隱藏優(yōu)先使用node.active false。禁用節(jié)點(diǎn)會(huì)使其停止渲染和所有組件更新開(kāi)銷(xiāo)遠(yuǎn)小于銷(xiāo)毀再創(chuàng)建。3.3 資源加載策略杜絕IO阻塞網(wǎng)絡(luò)資料提到“盡量避免IO操作”。在游戲運(yùn)行時(shí)進(jìn)行磁盤(pán)IO讀取資源是性能殺手會(huì)造成明顯的卡頓。預(yù)加載Preloading在進(jìn)入核心玩法場(chǎng)景如戰(zhàn)斗場(chǎng)景前在加載界面或上一個(gè)場(chǎng)景中使用cc.resources.preloadDir或cc.assetManager.bundles.load預(yù)加載所有必需的資源圖集、音效、預(yù)制體等。分包與動(dòng)態(tài)加載對(duì)于大型游戲不要把所有資源都放在主包。利用Cocos Creator的Asset Bundle功能將不同場(chǎng)景、功能的資源分成多個(gè)包按需動(dòng)態(tài)加載和釋放。紋理壓縮格式選擇針對(duì)不同平臺(tái)使用壓縮紋理能極大減少內(nèi)存占用和加載時(shí)間。在Cocos Creator的紋理導(dǎo)入設(shè)置中iOS優(yōu)先選擇PVRTC格式。這是iOS設(shè)備GPU原生支持的壓縮格式加載快顯存占用小。Android情況復(fù)雜一些。ETC2支持Alpha通道是OpenGL ES 3.0的標(biāo)準(zhǔn)現(xiàn)代Android設(shè)備大多支持。對(duì)于不支持ETC2的老設(shè)備可以采用ETC1 Alpha分離通道的方案或者回退到未壓縮格式。ASTC是更新更高效的格式但需要設(shè)備支持。小圖與UI對(duì)于大量小尺寸的UI圖標(biāo)即使不采用GPU壓縮格式也強(qiáng)烈建議使用RGBA4444格式替代RGBA8888可以節(jié)省大量?jī)?nèi)存。4. GPU側(cè)性能優(yōu)化實(shí)戰(zhàn)減輕圖形處理器的負(fù)擔(dān)當(dāng)CPU優(yōu)化到位后GPU可能成為瓶頸表現(xiàn)為幀率上不去但CPU占用并不高。對(duì)于2D游戲GPU瓶頸主要來(lái)自“過(guò)度繪制”O(jiān)verdraw。4.1 理解與解決“過(guò)度繪制”過(guò)度繪制是指同一個(gè)屏幕像素在單幀內(nèi)被多次繪制。例如一個(gè)不透明的背景Sprite覆蓋了整個(gè)屏幕然后上面又繪制了很多UI元素那么背景像素就被繪制了兩次背景一次UI元素所在區(qū)域又一次。過(guò)度繪制會(huì)浪費(fèi)GPU的填充率Fill Rate導(dǎo)致性能下降。Cocos Creator中的過(guò)度繪制優(yōu)化UI層級(jí)管理與裁剪Canvas組件的“Enable Culling”務(wù)必勾選。它會(huì)自動(dòng)剔除完全位于畫(huà)布可視區(qū)域外的節(jié)點(diǎn)避免無(wú)效繪制。Widget widget組件的合理使用雖然Widget能自動(dòng)布局但過(guò)度使用復(fù)雜的嵌套Widget會(huì)導(dǎo)致UI樹(shù)頻繁“臟”檢查觸發(fā)不必要的重排和重繪。對(duì)于靜態(tài)UI盡量使用固定坐標(biāo)或簡(jiǎn)單布局。Mask遮罩組件慎用Mask需要開(kāi)啟模板測(cè)試會(huì)增加GPU開(kāi)銷(xiāo)且會(huì)打斷合批。如果只是為了顯示圓形頭像可以考慮讓美術(shù)直接提供帶透明通道的圓形圖片而不是用矩形圖Mask。減少透明與半透明疊加半透明物體Blend為SRC_ALPHA: ONE_MINUS_SRC_ALPHA的渲染順序必須從后往前且無(wú)法進(jìn)行深度測(cè)試提前剔除容易導(dǎo)致過(guò)度繪制。盡量減少全屏半透明遮罩的層數(shù)。使用圖集并保持渲染順序盡量讓使用同一張圖集的節(jié)點(diǎn)在場(chǎng)景樹(shù)中連續(xù)排列這樣引擎更容易將它們合并批次減少狀態(tài)切換和繪制調(diào)用間接也利于GPU處理。4.2 著色器與高級(jí)渲染優(yōu)化當(dāng)你開(kāi)始使用自定義材質(zhì)Material和著色器Shader時(shí)就需要關(guān)注更底層的GPU優(yōu)化。避免在片段著色器中使用discard或alpha test正如網(wǎng)絡(luò)資料所指出的這會(huì)破壞某些移動(dòng)GPU如PowerVR的HSRHidden Surface Removal隱藏面消除優(yōu)化。HSR是一種在GPU片元著色階段之前提前剔除被遮擋像素的技術(shù)。使用discard或alpha test會(huì)使GPU無(wú)法提前確定像素的最終深度導(dǎo)致優(yōu)化失效。對(duì)于需要鏤空的效果應(yīng)盡量使用Alpha Blend透明度混合??刂浦鲝?fù)雜度片段像素著色器中的計(jì)算如復(fù)雜的光照模型、多次紋理采樣對(duì)性能影響很大。在移動(dòng)端堅(jiān)持“夠用原則”使用性能最優(yōu)的Blinn-Phong光照模型避免實(shí)時(shí)動(dòng)態(tài)陰影、屏幕空間反射等重型特性除非你的目標(biāo)用戶是高端旗艦機(jī)。減少實(shí)時(shí)燈光對(duì)于2D游戲或風(fēng)格化3D盡量使用烘焙光照Baked Lighting或光照貼圖Lightmap。動(dòng)態(tài)實(shí)時(shí)光源每一幀都要計(jì)算光照開(kāi)銷(xiāo)巨大。Cocos Creator的3D渲染管線支持光照貼圖烘焙應(yīng)充分利用。5. 內(nèi)存與包體優(yōu)化看不見(jiàn)的戰(zhàn)場(chǎng)性能不僅僅是幀率內(nèi)存占用過(guò)高會(huì)導(dǎo)致應(yīng)用被系統(tǒng)強(qiáng)制關(guān)閉OOM包體過(guò)大則影響下載轉(zhuǎn)化率。5.1 內(nèi)存管理紋理內(nèi)存是內(nèi)存占用的大頭。除了使用壓縮紋理還要及時(shí)釋放不再使用的紋理資源。使用cc.assetManager.releaseAsset或通過(guò)釋放Asset Bundle來(lái)卸載資源。注意直接設(shè)置texture null并不會(huì)立即釋放內(nèi)存需要調(diào)用釋放接口。JavaScript堆內(nèi)存避免內(nèi)存泄漏。確保被移除的節(jié)點(diǎn)、不再使用的對(duì)象其引用被正確置空以便JavaScript的垃圾回收器可以回收。特別是使用全局事件監(jiān)聽(tīng)時(shí)要在節(jié)點(diǎn)銷(xiāo)毀時(shí)onDestroy移除監(jiān)聽(tīng)。音頻內(nèi)存較長(zhǎng)的背景音樂(lè)使用流式播放避免一次性全部加載到內(nèi)存。短音效可以預(yù)加載到內(nèi)存中以求快速播放。5.2 構(gòu)建與包體優(yōu)化構(gòu)建發(fā)布時(shí)的選項(xiàng)合并圖集確保發(fā)布時(shí)勾選了合并圖集相關(guān)選項(xiàng)。壓縮紋理根據(jù)目標(biāo)平臺(tái)選擇正確的壓縮紋理格式。引擎裁剪在構(gòu)建面板的“功能裁剪”中移除項(xiàng)目中未使用的引擎模塊如物理引擎、視頻播放器、WebView等可以顯著減小引擎代碼體積。使用MD5 Cache為靜態(tài)資源文件名添加MD5后綴利于瀏覽器緩存。資源優(yōu)化音頻格式背景音樂(lè)使用.mp3短音效使用.ogg或.wav注意.wav未壓縮文件大。圖片尺寸確保圖片尺寸是2的冪次方如128, 256, 512…非2的冪次方紋理在GPU上可能會(huì)被填充到更大的尺寸造成浪費(fèi)。圖集利用率合理安排圖集減少空白區(qū)域提高空間利用率。Cocos Creator的自動(dòng)圖集功能在這方面做得不錯(cuò)。6. 性能分析工具鏈你的“火眼金睛”工欲善其事必先利其器。沒(méi)有數(shù)據(jù)支撐的優(yōu)化是盲目的。Cocos Creator內(nèi)置工具預(yù)覽模式性能面板在編輯器預(yù)覽游戲時(shí)可以打開(kāi)性能面板Profiler查看FPS、Draw Call、三角形數(shù)量、腳本耗時(shí)等基礎(chǔ)信息。這是最快捷的初步診斷工具。構(gòu)建后的調(diào)試模式通過(guò)cc.debug.setDisplayStats(true)可以在真機(jī)運(yùn)行時(shí)顯示性能統(tǒng)計(jì)面板。瀏覽器開(kāi)發(fā)者工具對(duì)于Web平臺(tái)Chrome DevTools的Performance和Memory面板是無(wú)價(jià)之寶。你可以錄制一段時(shí)間內(nèi)的性能數(shù)據(jù)精確分析每一毫秒CPU時(shí)間花在了哪里腳本、渲染、系統(tǒng)等并能查看內(nèi)存堆快照定位內(nèi)存泄漏。平臺(tái)專用工具Android使用Android Studio的Profiler或Systrace。對(duì)于GPU分析高通Adreno、ARMMali、ImaginationPowerVR都提供了各自的性能分析工具如Adreno Profiler可以深入分析GPU負(fù)載、紋理帶寬等。iOS使用Xcode的Instruments工具集特別是Time ProfilerCPU分析和Core AnimationGPU分析。第三方性能分析SDK可以考慮集成如騰訊PerfDog、UWA等第三方性能監(jiān)測(cè)平臺(tái)。它們可以提供云端真機(jī)測(cè)試、自動(dòng)化性能數(shù)據(jù)收集和報(bào)告適合團(tuán)隊(duì)進(jìn)行長(zhǎng)期性能監(jiān)控和回歸測(cè)試。7. 常見(jiàn)性能問(wèn)題排查與實(shí)戰(zhàn)案例這里整理一份從現(xiàn)象到原因再到解決方案的速查表方便你在遇到問(wèn)題時(shí)快速定位?,F(xiàn)象描述可能原因排查工具/方法解決方案游戲整體卡頓FPS低且不穩(wěn)定CPU瓶頸Draw Call過(guò)高JS邏輯復(fù)雜頻繁GC。1. 查看性能面板Draw Call數(shù)。2. 使用Chrome Performance錄制看Scripting耗時(shí)。3. 觀察JS Heap內(nèi)存曲線是否鋸齒狀頻繁GC。1. 合并圖集降低Draw Call。2. 優(yōu)化update邏輯緩存節(jié)點(diǎn)引用使用對(duì)象池。3. 避免在循環(huán)中創(chuàng)建臨時(shí)對(duì)象。幀率尚可但感覺(jué)不跟手有延遲單幀CPU耗時(shí)過(guò)長(zhǎng)導(dǎo)致幀間隔不均勻。可能某一幀有特別重的計(jì)算。使用性能分析工具如Chrome Performance查看幀時(shí)間線找到耗時(shí)特別長(zhǎng)的單幀分析該幀內(nèi)的調(diào)用棧。將重型計(jì)算如尋路、復(fù)雜AI決策分?jǐn)偟蕉鄮瓿苫蚍湃雜etTimeout/setInterval中異步執(zhí)行避免阻塞主線程。在低端機(jī)上卡頓嚴(yán)重高端機(jī)正常GPU填充率瓶頸過(guò)度繪制或使用了高端機(jī)才支持的渲染特性。1. 在低端機(jī)上開(kāi)啟GPU渲染模式分析如Android的GPU呈現(xiàn)模式分析。2. 檢查是否使用了復(fù)雜的自定義Shader。1. 優(yōu)化UI層級(jí)減少全屏半透明重疊。2. 簡(jiǎn)化或關(guān)閉低端機(jī)上的后期處理效果、動(dòng)態(tài)陰影等。3. 針對(duì)不同機(jī)型做畫(huà)質(zhì)分級(jí)。切換場(chǎng)景或打開(kāi)大型UI時(shí)瞬間卡頓同步加載大量資源阻塞主線程。在卡頓時(shí)使用工具查看調(diào)用棧確認(rèn)是否在同步cc.resources.load。1.預(yù)加載提前在后臺(tái)加載資源。2.異步加載使用cc.resources.load的回調(diào)或async/await。3.分幀加載將資源列表分到連續(xù)幾幀內(nèi)加載避免單幀卡死。游戲運(yùn)行一段時(shí)間后越來(lái)越卡甚至閃退內(nèi)存泄漏。1. 使用Chrome Memory工具定期拍攝堆快照對(duì)比快照查看持續(xù)增長(zhǎng)的對(duì)象類型。2. 檢查全局事件監(jiān)聽(tīng)、定時(shí)器、NodePool回收是否完整。1. 確保節(jié)點(diǎn)銷(xiāo)毀時(shí)移除了其注冊(cè)的所有事件監(jiān)聽(tīng)和定時(shí)器。2. 檢查對(duì)象池的get和put是否配對(duì)沒(méi)有節(jié)點(diǎn)被遺忘在場(chǎng)景中。3. 避免將復(fù)雜對(duì)象如節(jié)點(diǎn)存儲(chǔ)在全局變量或長(zhǎng)期存在的閉包中。包體體積過(guò)大未壓縮的圖片、音頻資源過(guò)多未進(jìn)行引擎裁剪包含多平臺(tái)冗余資源。查看構(gòu)建日志分析build目錄下各文件夾大小。1. 壓縮紋理和音頻。2. 在構(gòu)建面板進(jìn)行引擎裁剪。3. 使用Asset Bundle分包按需加載。4. 清理項(xiàng)目中未使用的資源。一個(gè)實(shí)戰(zhàn)案例我們?cè)幸粋€(gè)2D休閑游戲在某個(gè)活動(dòng)界面包含大量滾動(dòng)列表和圖標(biāo)滾動(dòng)時(shí)異常卡頓。通過(guò)性能面板發(fā)現(xiàn)Draw Call在滾動(dòng)時(shí)飆升至90。使用Chrome Performance工具深入分析發(fā)現(xiàn)罪魁禍?zhǔn)资橇斜眄?xiàng)中的圖標(biāo)——每個(gè)圖標(biāo)都是一個(gè)獨(dú)立的Sprite且因?yàn)閯?dòng)態(tài)設(shè)置SpriteFrame導(dǎo)致它們無(wú)法與背景合批。優(yōu)化方案是將列表項(xiàng)的背景和所有可能的圖標(biāo)預(yù)先合成為幾種固定的狀態(tài)圖作為整個(gè)列表項(xiàng)的SpriteFrame。這樣每個(gè)列表項(xiàng)無(wú)論顯示什么狀態(tài)都只對(duì)應(yīng)一個(gè)Draw Call。優(yōu)化后該界面滾動(dòng)時(shí)Draw Call穩(wěn)定在25以下流暢如絲。性能優(yōu)化是一場(chǎng)持久戰(zhàn)也是一門(mén)平衡的藝術(shù)。它沒(méi)有一勞永逸的銀彈需要你在開(kāi)發(fā)的每個(gè)階段都保持警惕養(yǎng)成“性能意識(shí)”。從資源導(dǎo)入規(guī)范到代碼編寫(xiě)習(xí)慣再到最終的測(cè)試調(diào)優(yōu)將本文提到的原則和方法融入你的日常開(kāi)發(fā)流程你就能打造出不僅好玩而且流暢、穩(wěn)定的高品質(zhì)游戲。記住最好的優(yōu)化往往是那些在問(wèn)題發(fā)生之前就做好的設(shè)計(jì)。