1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
Unity移動端性能優化
馮委
馮委
遊戲開發
262人讚同了該文章
1.渲染
利用reflect probe代替反射、折射,盡量不用RTT、GrabPass、RenderWithShader、CommandBuffer.Blit (BuiltinRenderTextureType.CurrentActive...)
建立統一後處理框架(bloom、hdr、DOF等)代替多後處理,可以共用模糊函數,減少多次blit;另外要注意RTT的尺寸。
空氣折射、熱浪扭曲等使用GrabPass不是所有硬件都支持,改為RTT或者後處理來優化。
建立統一shader材質代替單一shader,充分利用shader_feature、multi_compile,並將宏開關顯示於界面。
圖像混合代替多通道紋理,陰影投射、陰影接收、MetaPass、forwardadd 等pass不需要時要剔除。
少用alpha test、discard、clip、Alpha Converage等,因為會影響Early-Z Culling、HSR的優化。
避免Alpha Blend穿透問題(權重混合、深度剝離等透明排序方法代價太大了)。
光照貼圖代替動態陰影、盡量不用實時光;陰影貼圖、環境貼圖用16位代替32位;利用projector+rtt或者光圈代替實時陰影。
將環境參數(風、雨、太陽)等shader全局參數統一管理。
非主角可以用matcap代替pbr、無金屬不一定要用pbr,仔細選擇物理渲染所用的FDG(F:schlick、cook-torrance、lerp、要求不高用4次方,D:blinn-phong、beckmann、 GGX、GGX Anisotropic,G:neumann、cook-torrance、Kelemen、SmithGGX;standard shader要注意選擇BRDF1-BRDF3),渲染要求不高時不用GGX;可以用LH來優化GGX。
用fixed、half代替float,建立shader統一類型(fixed效率是float的4倍,half是float的2倍),小心選擇shader變量的修飾(uniform、static、全局),選擇Mobile或Unlit目錄下shader
使用高低配渲染,內存足夠時可以考慮開啟mipmap
使用surface shader注意關掉不用的功能,比如:noshadow、noambient、novertexlights、nolightmap、nodynlightmap、nodirlightmap、nofog、nometa、noforwardadd等
standard shader的變體太多(3萬多),導致編譯時間較長,內存佔用也很驚人(接近1G),如果使用要關掉沒用的shader_feature,比如:_PARALLAXMAP、SHADOWS_SOFT、DIRLIGHTMAP_COMBINED DIRLIGHTMAP_SEPARATE、_DETAIL_MULX2、 _ALPHAPREMULTIPLY_ON;另外要去掉多餘的pass
shaderforge、Amplify Shader Editor生成的shader有多餘代碼要程序專門優化,Amplify Shader Editor功能更強大一些,而且開源,建議學習。
不要用unity自帶terrian,因為即使只用3張splat圖,shader也是對應4個的,建議T4M或者轉為mesh。
模型和材質相同且數量巨大時用Instance來優化,比如草。
利用查找紋理(LUT)來優化複雜的光照渲染,比如:皮膚、頭髮、噴漆等。
盡量不要使用Procedural Sky,計算瑞麗散射和米氏散射效率比較低。
盡量不要使用speedtree,改為模型加簡單樹葉動畫,不過SpeedTreeWind.cginc裡面的動畫函數很豐富,TerrianEngine中的SmoothTriangleWave很好用。
多用調試工具檢查shader性能,常用工具有:FrameDebug、Nsight、RenderDoc 、AMD GPU ShaderAnalyzer / PVRShaderEditor、Adreno Profiler 、騰訊Cube、UWA等;另外可以內置GM界面,比如開關陰影,批量替換shader等方便真機調試。
2.腳本
減少GetComponent、find等查找函數在Update等循環函數中的調用、go.CompareTag代替go.tag 、
減少SendMessage等同步函數調用;減少字符串連接;for代替foreach,5.5以後版本foreach已經優化過了;少用linq;
大資源改為異步加載
合理處理協程調用
將AI、網絡等放在單獨線程
發布優化:關閉log、剔除代碼
偽隨機
腳本掛載類改為Manager等全局類實現
lua中盡量不實現update、fixedupdate等循環函數,lua和csharp互調用的效率比較低。
3.內存管理
池子管理粒子、float UI等小資源,頻繁地GC會造成卡頓
必要時主動調用GC.Collect()
按照不同資源、不同設備管理資源生命週期,Resources.Load和Assetbundle統一接口,利用引用計數來管理生命週期,並打印和觀察生命週期。保證資源隨場景而卸載,不常駐內存,確定哪些是預加載,哪些洩漏。
內存洩漏(減少駐留內存):Container內資源不remove掉用Resources.UnloadUnusedAssets是卸載不掉的;對於這種情況,建議直接通過Profiler Memory中的Take Sample來對其進行檢測,通過直接查看WebStream或SerializedFile中的AssetBundle名稱,即可判斷是否存在“洩露”情況;通過Android PSS/iOS Instrument反饋的App線程內存來查看;
堆內存過大:避免一次性堆內存的過大分配,Mono的堆內存一旦分配,就不會返還給系統,這意味著Mono的堆內存是只升不降的。常見:高頻調用new;log輸出;
CPU佔用高:NGui的重建網格導致UIPanel.LateUpdate(按照靜止、移動、高頻移動來切分);NGUI錨點自身的更新邏輯也會消耗不少CPU開銷。即使是在控件靜止不動的情況下,控件的錨點也會每幀更新(見UIWidget.OnUpdate函數),而且它的更新是遞歸式的,使CPU佔用率更高。因此我們修改了NGUI的內部代碼,使錨點只在必要時更新。一般只在控件初始化和屏幕大小發生變化時更新即可。不過這個優化的代價是控件的頂點位置發生變化的時候(比如控件在運動,或控件大小改變等),上層邏輯需要自己負責更新錨點。加載用協程; 控制同一個UIPanel中動態UI元素的數量,數量越多,所創建的Mesh越大,從而使得重構的開銷顯著增加。比如,戰鬥過程中的HUD血條可能會大量出現,此時,建議研發團隊將運動血條分離成不同的UIPanel,每組UIPanel下5~10個動態UI為宜。這種做法,其本質是從概率上盡可能降低單幀中UIPanel的重建開銷。
資源冗餘:AssetBundle打包打到多份中;動態修改資源導致的Instance拷貝多份(比如動態修改材質,Renderer.meterial,Animation.AddClip)。
磁盤空間換內存:對於佔用WebStream較大的AssetBundle文件(如UI Atlas相關的AssetBundle文件等),建議使用LoadFromCacheOrDownLoad或CreateFromFile來進行替換,即將解壓後的AssetBundle數據存儲於本地Cache中進行使用。這種做法非常適合於內存特別吃緊的項目,即通過本地的磁盤空間來換取內存空間
4.美術
建立資源審查規範和審查工具:PBR材質貼圖製作規範、場景製作資源控制規範、角色製作規範、特效製作規範;利用AssetPostprocessor建立審查工具。
壓縮紋理、優化精靈填充率、壓縮動畫、壓縮聲音、壓縮UI(九宮格優於拉伸);嚴格控制模型面數、紋理數、角色骨骼數。
粒子:錄製動畫代替粒子、減少粒子數量、粒子不要碰撞
角色:啟用Optimize Game Objects減少節點,使用(SimpleLOD、Cruncher)優化面數。
模型:導入檢查Read/Write only、Optimize Mesh、法線切線、color、禁用Mipmap
壓縮紋理問題:壓縮可能導致色階不足;無透明通道用ETC1,現在安卓不支持ETC2已不足5%,建議放棄分離通道辦法。
UI:盡可能將動態UI元素和靜態UI元素分離到不同的UIPanel中(UI的重建以UIPanel為單位),從而盡可能將因為變動的UI元素引起的重構控制在較小的範圍內; 盡可能讓動態UI元素按照同步性進行劃分,即運動頻率不同的UI元素盡可能分離放在不同的UIPanel中; 盡可能讓動態UI元素按照同步性進行劃分,即運動頻率不同的UI元素盡可能分離放在不同的UIPanel中;
ugui:可以充分利用canvas來切分不同元素。
大貼圖會導致卡頓,可以切分為多個加載。
iOS使用mp3壓縮、Android使用Vorbis壓縮
5.批次
開啟static batch
開啟dynamic batch:要求模型小於900頂點,用法線小於300,用切線小於180,縮放不一致、使用lightmap、多通道材質等會使dynamic batch無效。
減少GameObject,場景模型數量對fps影響巨大。
批次不是越少越好,過大的渲染數據會給總線傳輸帶來壓力。
6.物理
不需要移動的物體設為Static
不要用Mesh碰撞,角色不用碰撞體
觸發器邏輯優化
尋路頻率、AI邏輯頻率、Fixed Timestep、降幀到30
出現卡頓的複雜計算,例如尋路、大量資源加載可以用分幀或者協成異步來處理
編輯於2017-04-01