Cocos2d-x+Lua游戲的優化總結
近期游戲準備出安卓版本,在安卓上的性能表現不佳。經過一周多的優化,在性能上取得了較大的提升。游戲采用Cocos2d-x3.2+Lua進行開發,以下將在渲染效率,CPU效率,包大小等方面進行總結。
渲染效率
紋理格式 – 運行效率 內存 包大小
- 所有的圖片都通過一個python腳本(調用TexturePacker的命令行工具)自動轉換為RGBA4444編碼的格式。然后判斷當前平臺為安卓時,將默認紋理格式轉換為RGBA4444。 </ul>
- 以上的過程會發現一種比較「反常」的現象,就是轉成RGBA4444的圖片要比原來的圖片要大。所以在腳本中不能單純的轉換,需要對比轉換前后的大小,只轉換變得更小的圖片。
- 還需要注意性能和表現的平衡。有些圖片轉成RGBA4444后看起來太糙,嚴重的影響了游戲的視覺體驗。對此需要小心的針對處理。處理方法為:在這些紋理使用前將默認紋理格式設置為RGBA8888,當紋理使用后再將其設置為之前的默認紋理格式。
左圖是沒有做處理的游戲截圖,可見相當不平滑的光線和背景。 右圖是只針對背景和光暈的紋理設為RGBA8888處理,視覺體驗一下子就回歸了。 - 壓縮成RGBA4444格式的PNG圖片,還可以用pngquant工具進一步壓縮,而視覺體驗肉眼感受幾乎沒有變化。這樣可以進一步的減少包的大小。
- RGBA4444的紋理內存使用量要比默認的RGBA8888小一半,所以可以很大的減輕游戲的內存壓力。而且和PVR ETC等壓縮紋理相比,可以完全共用一套代碼,不需要寫額外處理邏輯,同時兼容iOS和Android兩大移動平臺。所以我認為性價比還是很高的。 </ul>
- 游戲采用CocoStudio來制作骨骼動畫。CocoStudio導出的骨骼動畫導出的圖片默認大小是POT(power of two)。這其實會造成很多空白像素的浪費,這些空白像素不僅會讓圖片變大,還會增加紋理的內存。
- 具體辦法是:將導出的POT圖片,經過美術或工具的剪裁掉多余的空白像素,使之變成NPOT(non power of two),然后修改一下plist文件中<texture>中的width和height值,經試驗,對實際的使用是沒有任何影響的。
- 通過把所有POT格式的圖片裁剪為NPOT,不僅可以縮減圖片的體積,還能減少紋理的內存占用。 </ul>
- 在同事對整個包進行DrawCall和OverDraw分析后發現,消除場景內還保留著天空背景。而這層背景實際是玩家看不到,因為它完全被消除場景擋住了。但是它會帶來全屏的繪制造成了全屏范圍的OverDraw,而且帶來了很多額外不必要的DrawCall。將其隱藏后,FPS在低端機上提升明顯。
- 需要把這些看不到的東西全部隱藏或移除掉,否則它們會造成OverDraw和不必要的DrawCall,增加了GPU的負擔。
- 隱藏的辦法,有些童鞋喜歡將其透明度設為0,但是這樣是不會降低DrawCall的。最好的方法是將其visble設為false。
- 還有就是場景內有很多細碎的東西,如果它們都是一張張散圖儲存的話,會使DrawCall居高不下,從而可能導致FPS下降。why are draw calls expensive?
- 解決辦法就是盡可能的將經常一起出現在屏幕上的小圖合并成一張大圖。 </ul>
- 避免在循環內做重復的運算。因為如果計算值在整個循環內都不會變的話,那么每次循環都去計算就是浪費CPU周期,應該將計算結果緩存在循環外部。
- 想辦法避免開銷大的函數(如:開方函數,三角函數),尋找簡單運算的替代方案。如:距離的比較可以不用開方先求出距離,而是直接用平方運算進行比較即可。
- 盡可能的避免同時多個的cc.RepeatForever。在低端機上發現在對較多對象調用cc.RepeatForever時,FPS下降顯著。原因可能是每幀帶來的計算,和因此頻繁觸發的Lua GC。而垃圾回收是一個十分耗費CPU時間的操作。
- 優化算法,剪枝,去除冗余的計算。在游戲內的碰撞系統是這么進行優化的:原來對每一個球,會遍歷整個空間的碰撞體和墻壁進行碰撞檢測;優化后的算法是取球當前的坐標,轉換為格子坐標,然后只取格子周邊6個格子內的碰撞體和墻壁進行碰撞檢測。效率提高了很多倍。
- 避免頻繁的開辟內存,對象最好實現復用。開辟內存也是一項很耗費CPU的操作,尤其是在移動設備上內存緊張時。對象能重用盡量重用(建立對象池)。Lua內的表能初始化大小,盡量先初始化大小,否則rehash的操作很費時。如何編寫高性能的Lua代碼?
- 用效率更高的庫來替換,比如用cJson來替換Lua json,用pugixml來替代tinyxml2。或者將效率低的模塊嘗試用更低級的語言進行重寫。
- 出包時,關掉所有的print語句。你們都知道輸出到緩沖區的log有多卡。 </ul>
- 預測即將用到的紋理和資源,提前將其進行異步加載。這樣能在用到時,可以減少掉紋理加載的時間,給玩家的感覺上會更流暢一些。 </ul>
- 由于引擎使用的是Cocos2d-x 3.2版本,所以沒有3.3帶來的模塊精簡的功能。但是我們也可以自己去小心翼翼的移除掉游戲根本不會用到的模塊。比如:物理引擎,3d模塊,CocosBuilder spine等等。
- 具體的方法是:通過adt的打包日志,分析有哪些庫被編譯進最終的so文件中,然后去項目內一個一個搜索這些庫的名稱。找到其對應的Android.mk文件,然后嘗試移除掉無用庫文件,然后嘗試編譯,確保游戲能正確運行。 </ul> 來自:http://wuzhiwei.net/opitimize_of_cocos2d-x_lua_game/
-- 安卓啟用4444紋理 if targetPlatform == cc.PLATFORM_OS_ANDROID then cc.Texture2D:setDefaultAlphaPixelFormat(cc.TEXTURE2_D_PIXEL_FORMAT_RGB_A4444) end
紋理剪裁 – 內存 包大小
DrawCall OverDraw
CPU計算
其他
異步加載
移除不用的庫
本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!