我的思路
在移動設備上打開UI界面卡頓,等待時間長,頁面白塊,等等體驗是很不好的。本文記錄我在工作中解決UI卡頓的方法。
我主要從以下方面入手
資源量
界面打開做的操作
界面自身的邏輯
IO的讀寫(包括收到的網絡協議數據量)
我的環境
項目類型:大型3DMMOARPG
Unity3D 5.3.7 基於UGUI,UI基礎框架使用KSFramework:https://github.com/mr-kelly/KSFramework
客戶端配置文件通過sqlite存儲(在Lua中讀取數據)
測試機型:
OPPOA57 中端機器 ,3G內存
詳細參數:http://detail.zol.com.cn/1161/1160598/param.shtml
優化目標
打開界面的瞬間,就能得到反饋,等待時間在0.2s之內。
頁面的內容可以是逐步顯示,但不希望出現卡住的現象。
UI的Assetbundle大小
建議一個UI界面的的Assetbundle文件大小在1mb以內,且依賴關系不要超過三個,在打包出來的*.manifest文件中(Dependencies節點)可以看到資源依賴關系。
如果一個界面的圖片量過多,美術可以考慮在設計上精簡圖集,重復利用,九宮格,抽離大的背景圖等方法,減少資源量。
建議:一個界面使用一個圖集,減少圖集間的交叉引用。
UI圖占用的內存
查看單個界面的資源占用內存大小
1、點擊 Window - 點擊Profiler ,打開Profiler ,切換到 Memory頁簽
2、點擊 Detaild - 點擊 Take Sample ,選擇 Assets/Texture2D,查看每張圖片占用的內存
建議:單個界面圖集的內存占用控制在1~2M之內,其它特殊情況,可以考慮做成大圖加載
整個UI界面的Gameobject數量
如果UI界面中Gameobject的數量過多,在加載Assetbundle實例化Gameobject時,耗時會更長。
我的例子:
(1個道具Prefab的Gameobject數量在10個左右)
統計UI界面的gameobject數量腳本
[MenuItem("UI/統計當前場景的Gameobject數量")] public static void MenuGameobjectCount() { var obj = GameObject.FindObjectOfType<UIWindowAsset>(); if (obj) { var graphics = obj.GetComponentsInChildren<Transform>(true); Debug.LogFormat("當前場景的Gameobject數量:{0}",graphics.Length); } }
建議:單個界面的gameobject數量控制在100以內
打開界面做的操作
減少在UI打開瞬間做的操作,耗時的計算或者操作可以延時處理。
每幀生成Gameobject
如果列表的數量過多,建議每幀或者間隔多少幀進行Instantiate操作。
示例代碼:
function UIRewardMonthly:Update() if self.index and self.index <= self.maxCell then local item = GameObject.Instantiate(self.itemCell.gameObject) item.transform:SetParent(self.scrollContent.transform, false) self:DoRenderItem(self.index, item.transform, self.uiCache[self.index]) if self.index == self.maxCell then --print("全部格子生成完成") end self.index = self.index + 1 end end
IO的讀取
在移動端的IO操作是很耗時的,比如讀寫配置文件。
解析網絡數據也是一種IO的操作,如果網絡數據量大,解析也是較耗時的。
建議:
1、盡量減少在打開界面時做IO的操作。
2、對需要的數據提前處理,數量很多的網絡數據可以進行分頁。
3、對於本地數據可以進行緩存,避免在循環中進行查詢或文件讀寫。