原文地址 http://www.fx114.net/qa-75-172454.aspx
使用Profiler工具分析內(nèi)存占用情況
System.ExecutableAndDlls:系統(tǒng)可執(zhí)行程序和DLL汇四,是只讀的內(nèi)存,用來執(zhí)行所有的腳本和DLL引用。不同平臺和不同硬件得到的值會不一樣秋冰,可以通過修改Player
Setting的Stripping Level來調(diào)節(jié)大小。
Ricky:我試著修改了一下Stripping Level似乎沒什么改變婶熬,感覺雖占用內(nèi)存大但不會影響游戲運行剑勾。我們暫時忽略它吧(- -)!
GfxClientDevice:GFX(圖形加速\圖形加速器\顯卡
(GraphicsForce Express))客戶端設(shè)備埃撵。
Ricky:雖占用較大內(nèi)存,但這也是必備項虽另,沒辦法優(yōu)化暂刘。繼續(xù)忽略吧(- -)!!
ManagedHeap.UsedSize:托管堆使用大小。
Ricky:重點監(jiān)控對象捂刺,不要讓它超過20MB谣拣,否則可能會有性能問題!
ShaderLab:Unity自帶的著色器語言工具相關(guān)資源族展。
Ricky:這個東西大家都比較熟悉了森缠,忽略它吧。
SerializedFile:序列化文件仪缸,把顯示中的Prefab贵涵、Atlas和metadata等資源加載進(jìn)內(nèi)存。
Ricky:重點監(jiān)控對象恰画,這里就是你要監(jiān)控的哪些預(yù)設(shè)在序列化中在內(nèi)存中占用大小宾茂,根據(jù)需求進(jìn)行優(yōu)化。
PersistentManager.Remapper:持久化數(shù)據(jù)重映射管理相關(guān)
Ricky:與持久化數(shù)據(jù)相關(guān)拴还,比如AssetBundle之類的跨晴。注意監(jiān)控相關(guān)的文件。
ManagedHeap.ReservedUnusedSize:托管堆預(yù)留不使用內(nèi)存大小自沧,只由Mono使用坟奥。
Ricky:無法優(yōu)化。
許多貼圖采用的Format格式是ARGB
32 bit所以保真度很高但占用的內(nèi)存也很大拇厢。在不失真的前提下爱谁,適當(dāng)壓縮貼圖,使用ARGB 16
bit就會減少一倍孝偎,如果繼續(xù)Android采用RGBA Compressed ETC2 8 bits(iOS采用RGBA Compressed
PVRTC 4 bits)访敌,又可以再減少一倍。把不需要透貼但有alpha通道的貼圖衣盾,全都轉(zhuǎn)換格式Android:RGB
Compressed ETC 4 bits寺旺,iOS:RGB Compressed PVRTC 4 bits。
當(dāng)加載一個新的Prefab或貼圖势决,不及時回收阻塑,它就會永駐在內(nèi)存中,就算切換場景也不會銷毀果复。應(yīng)該確定物體不再使用或長時間不使用就先把物體制空(null)陈莽,然后調(diào)用Resources.UnloadUnusedAssets(),才能真正釋放內(nèi)存。
有大量空白的圖集貼圖走搁,可以用TexturePacker等工具進(jìn)行優(yōu)化或考慮合并到其他圖集中独柑。
AudioManager:音頻管理器
Ricky:隨著音頻文件的增多而增大。
AudioClip:音效及聲音文件
Ricky:重點優(yōu)化對象私植,播放時長較長的音樂文件需要進(jìn)行壓縮成.mp3或.ogg格式忌栅,時長較短的音效文件可以使用.wav 或.aiff格式。
Cubemap:立方圖紋理
Ricky:這個一般在天空盒中比較常見曲稼,我也不知道如何優(yōu)化這個索绪。。贫悄。
Mesh:模型網(wǎng)格
Ricky:主要檢查是否有重復(fù)的資源者春,還有盡量減少點面數(shù)。
Mesh:場景中使用的網(wǎng)格模型
Ricky:注意網(wǎng)格模型的點面數(shù)清女,能合并的mesh盡量合并钱烟。
1)ManagedHeap.UsedSize: 移動游戲建議不要超過20MB.
2)SerializedFile: 通過異步加載(LoadFromCache、WWW等)的時候留下的序列化文件,可監(jiān)視是否被卸載.
3)WebStream: 通過異步WWW下載的資源文件在內(nèi)存中的解壓版本嫡丙,比SerializedFile大幾倍或幾十倍拴袭,不過我們現(xiàn)在項目中展示沒有。
4)Texture2D: 重點檢查是否有重復(fù)資源和超大Memory是否需要壓縮等.
5)AnimationClip: 重點檢查是否有重復(fù)資源.
6)Mesh: 重點檢查是否有重復(fù)資源.
1.Device.Present:
1)GPU的presentdevice確實非常耗時曙博,一般出現(xiàn)在使用了非常復(fù)雜的shader.
2)GPU運行的非秤悼蹋快,而由于Vsync的原因父泳,使得它需要等待較長的時間.
3)同樣是Vsync的原因般哼,但其他線程非常耗時,所以導(dǎo)致該等待時間很長惠窄,比如:過量AssetBundle加載時容易出現(xiàn)該問題.
4)Shader.CreateGPUProgram:Shader在runtime階段(非預(yù)加載)會出現(xiàn)卡頓(華為K3V2芯片).
5)StackTraceUtility.PostprocessStacktrace()和StackTraceUtility.ExtractStackTrace(): 一般是由Debug.Log或類似API造成蒸眠,游戲發(fā)布后需將Debug API進(jìn)行屏蔽。
2.Overhead:
1)一般情況為Vsync所致.
2)通常出現(xiàn)在Android設(shè)備上.
3.GC.Collect:
原因:
1)代碼分配內(nèi)存過量(惡性的)
2)一定時間間隔由系統(tǒng)調(diào)用(良性的).
占用時間:
1)與現(xiàn)有Garbage size相關(guān)
2)與剩余內(nèi)存使用顆粒相關(guān)(比如場景物件過多杆融,利用率低的情況下楞卡,GC釋放后需要做內(nèi)存重排)
4.GarbageCollectAssetsProfile:
1)引擎在執(zhí)行UnloadUnusedAssets操作(該操作是比較耗時的,建議在切場景的時候進(jìn)行)。
2)盡可能地避免使用Unity內(nèi)建GUI脾歇,避免GUI.Repaint過渡GCAllow.
3)if(other.tag == a.tag)改為other.CompareTag(a.tag).因為other.tag為產(chǎn)生180B的GC Allow.
4)少用foreach蒋腮,因為每次foreach為產(chǎn)生一個enumerator(約16B的內(nèi)存分配),盡量改為for.
5)Lambda表達(dá)式藕各,使用不當(dāng)會產(chǎn)生內(nèi)存泄漏.
5.盡量少用LINQ:
1)部分功能無法在某些平臺使用.
2)會分配大量GC Allow.
6.控制StartCoroutine的次數(shù):
1)開啟一個Coroutine(協(xié)程)池摧,至少分配37B的內(nèi)存.
2)Coroutine類的實例 -> 21B.
3)Enumerator -> 16B.
7.使用StringBuilder替代字符串直接連接.
8.緩存組件:
1)每次GetComponent均會分配一定的GC Allow.
2)每次Object.name都會分配39B的堆內(nèi)存.
.框架設(shè)計層面。
一個相對中大型的游戲激况,系統(tǒng)非常的多作彤。這時候合理的適時的釋放內(nèi)存有助于游戲的正常體驗踢京,甚至可以防止內(nèi)存快速到達(dá)峰值,導(dǎo)致設(shè)備Crash宦棺。
目前主流平臺機(jī)型可用內(nèi)存:
Android平臺:在客戶端最低配置以上,均需滿足以下內(nèi)存消耗指標(biāo)(PSS):
1)內(nèi)存1G以下機(jī)型:最高PSS<=150MB
2)內(nèi)存2G的機(jī)型:最高PSS<=200MB
iOS平臺:在iPhone4S下運行黔帕,消耗內(nèi)存(real mem)不大于150MB
1.場景切換時避開峰值代咸。
當(dāng)前一個場景還未釋放的時候,切換到新的場景成黄。這時候由于兩個內(nèi)存疊加很容易達(dá)到內(nèi)存峰值呐芥。解決方案是,在屏幕中間遮蓋一個Loading場景奋岁。在舊的釋放完思瘟,并且新的初始化結(jié)束后,隱藏Loading場景闻伶,使之有效的避開內(nèi)存大量疊加超過峰值滨攻。
2.GUI模塊加入生命周期管理。
主角蓝翰、強(qiáng)化光绕、技能、商城畜份、進(jìn)化诞帐、背包、任務(wù)等等爆雹。通常一個游戲都少不了這些系統(tǒng)停蕉。但要是全部都打開,或者這個時候再點世界地圖钙态,外加一些邏輯數(shù)據(jù)內(nèi)存的占用等等慧起。你會發(fā)現(xiàn),內(nèi)存也很快就達(dá)到峰值册倒。
這時候有效的管理系統(tǒng)模塊生命周期就非常有必要完慧。首先將模塊進(jìn)行劃分:
1)經(jīng)常打開 Cache_10;
2)偶爾打開 Cache_5剩失;
3)只打開一次 Cache_0屈尼。
創(chuàng)建一個ModuleMananger
類,內(nèi)部Render方法每分鐘輪詢一次拴孤。如果是“Cache_0”這個類型脾歧,一關(guān)閉就直接Destroy釋放內(nèi)存;“Cache_10”這個類型為10分鐘后自動釋放內(nèi)存演熟;"
Cache_5"這種類型為5分鐘后自動釋放內(nèi)存鞭执。每次打開模塊司顿,該模塊就會重新計時。這樣就可以有效合理的分配內(nèi)存兄纺。
1大溜、 由于實時對戰(zhàn)游戲的數(shù)據(jù)包數(shù)量巨大,早期版本的幀同步策略會導(dǎo)致比較明顯的卡頓估脆,通過進(jìn)行數(shù)據(jù)包的合并與優(yōu)化逐漸解決了卡頓問題钦奋;
2、 頻繁創(chuàng)建和銷毀的小兵對象讓CPU爆表了疙赠,大量的小兵如果采用實時內(nèi)存的分配和回收付材,會產(chǎn)生大量的內(nèi)存碎片和系統(tǒng)開銷,解決方法之一就是采用高效的對象池進(jìn)行優(yōu)化圃阳,對每個內(nèi)存對象的狀態(tài)進(jìn)行操作即可厌衔;
3、 性能分析過程中捍岳,發(fā)現(xiàn)單人同屏和多人同屏?xí)r的開銷都很大富寿,通過視野裁剪技術(shù),使得玩家視野外的不必要的特效和渲染可以全部關(guān)閉锣夹,極大降低了CPU作喘、GPU和內(nèi)存的開銷;
4晕城、 在高中低三檔機(jī)型上玩游戲時泞坦,分別加載不同層次的特效包,這也有助于降低CPU和內(nèi)存的開銷砖顷;性能分析過程中發(fā)現(xiàn)副本內(nèi)wwise音頻組件占了30%的CPU時間贰锁,果斷拋棄之,采用Unity自帶音頻功能滤蝠,優(yōu)化很明顯豌熄;
5、 游戲內(nèi)界面采用了UGUI的方式實現(xiàn)物咳,但大量的實時UI變化使得副本內(nèi)每幀會有230以上的drawcall锣险,導(dǎo)致中低端機(jī)型感受到明顯卡頓,最終采用UGUI+自研究UI的組合拳览闰,重寫了一套緊密結(jié)合游戲自身特性的UI來實現(xiàn)戰(zhàn)斗血條和浮動文字的效果芯肤。
6、 資源使用總量是否在合理范圍之內(nèi)压鉴。
7崖咨、 一個場景內(nèi)的資源重復(fù)率。
8油吭、 資源對象拷貝的數(shù)量是否合理击蹲。
9署拟、 場景切換時保留的資源詳情。
10歌豺、 網(wǎng)格推穷、紋理、音頻类咧、動畫馒铃、GameObject等資源是否超標(biāo)。
11轮听、 貼圖:
12、 l 控制貼圖大小岭佳,盡量不要超過 1024x1024血巍;
13、 l 盡量使用2的n次冪大小的貼圖珊随,否則GfxDriver里會有2份貼圖述寡;
14、 l 盡量使用壓縮格式減小貼圖大幸抖础鲫凶;
15、 l 若干種貼圖合并技術(shù)衩辟;
16螟炫、 l 去除多余的alpha通道;
17艺晴、 l 不同設(shè)備使用不同的紋理貼圖昼钻,分層顯示;
18封寞、
19然评、 模型:
20、 l 盡量控制模型的面數(shù)狈究,小于1500會比較合適碗淌;
21、 l 不同設(shè)備使用不同的模型面數(shù)抖锥;
22亿眠、 l 盡量保持在30根骨骼內(nèi);
23磅废、 l 一個網(wǎng)格不要超過3個material缕探;
24、 動畫:
25还蹲、 l N種動畫壓縮方法爹耗;
26耙考、 l 盡量減少骨骼數(shù)量;
27潭兽、 聲音:
28倦始、 l 采用壓縮MP3 和 wav;
29山卦、 資源方面的優(yōu)化:
30鞋邑、 l 使用 Resource.Load 方法在需要的時候再讀取資源;
31账蓉、 l 各種資源在使用完成后枚碗,盡快用Resource.UnloadAsset和UnloadUnusedAsset卸載掉;
32铸本、 l 靈活運用AssetBundle的Load和Unload方法動態(tài)加載資源肮雨,避免主要場景內(nèi)的初始化內(nèi)存占用過高;(實現(xiàn)起來真的很難…)
33箱玷、 l 采用www加載了AssetBundle后怨规,要用www.Dispose 及時釋放;
34锡足、 l 在關(guān)卡內(nèi)謹(jǐn)慎使用DontDestroyOnLoad波丰,被標(biāo)注的資源會常駐內(nèi)存钟鸵;
35惯吕、 代碼的優(yōu)化:
36谋右、 l 盡量避免代碼中的任何字符串連接惑艇,因為這會給GC帶來太多垃圾消恍;
37痢毒、 l 用簡單的“for”循環(huán)代替“foreach”循環(huán)漏隐;
38幔崖、 l 為所有游戲內(nèi)的動態(tài)物體使用內(nèi)存對象池珠插,可以減少系統(tǒng)開銷和內(nèi)存碎片惧磺,復(fù)用對象實例,構(gòu)建自己的內(nèi)存管理模式捻撑,減少Instantiate和Destory磨隘;
39、 l 盡量不使用LINQ命令顾患,因為它們一般會分配中間緩器番捂,而這很容易生成垃圾內(nèi)存;
40江解、 l 將引用本地緩存到元件中會減少每次在一個游戲?qū)ο笾惺褂?“GetComponent” 獲取一個元件引用的需求设预;
41、 l 減少角色控制器移動命令的調(diào)用犁河。移動角色控制器會同步發(fā)生鳖枕,每次調(diào)用都會耗損較大的性能魄梯;
42、 l 最小化碰撞檢測請求(例如raycasts和sphere checks)宾符,盡量從每次檢查中獲得更多信息酿秸;
43、 l AI邏輯通常會生成大量物理查詢魏烫,建議讓AI更新循環(huán)設(shè)置低于圖像更新循環(huán)辣苏,以減少CPU負(fù)荷;
44哄褒、 l 要盡量減少Unity回調(diào)函數(shù)稀蟋,哪怕是空函數(shù)也不要留著;(例如空的Update呐赡、FixedUpdate函數(shù))
45退客、 l 盡量少使用FindObjectsOfType函數(shù),這個函數(shù)非常慢罚舱,盡量少用且一定不要在Update里調(diào)用井辜;
46绎谦、 l 千萬一定要控制mono堆內(nèi)存的大泄苊啤;
47窃肠、
48包个、 unity3D 對于移動平臺的支持無可厚非,但是也有時候用Unity3D 開發(fā)出來的應(yīng)用冤留、游戲在移動終端上的運行有著明顯的效率問題碧囊,比如卡、畫質(zhì)等各種問題纤怒。自己在做游戲開發(fā)的時候偶有所得糯而。對于主要影響性能的因素做個總結(jié)。
49泊窘、
50熄驼、 主要因素有:
51、 1. Savedby batching 值過大 ---- > 這個值主要是針對Mesh的批處理烘豹,這個值越高瓜贾,應(yīng)用就越卡
52、 2. Drawcall值過大 ---- > Drawcall 值過大携悯,所需要的 GPU 的處理性能較高祭芦,從而導(dǎo)致CPU的計算時間過長,于是就卡了
53憔鬼、 3. 點龟劲、面過多 ----> 點胃夏、面過多,GPU 根據(jù)不同面的效果展開計算咸灿,并且CPU計算的數(shù)據(jù)也多构订,所以效果出來了,但是卡巴斯基
54避矢、 由于 Saved by batching 和 Drawcall 值過大所引起的卡的問題我所做的優(yōu)化方式有:
55悼瘾、 1. 對于模型 :Mesh 合并,有個不錯的插件(DrawCallMinimizer ---> 直接上AssetStore 下載即可审胸,免費的亥宿,而且有文檔,很容易上手)
56砂沛、 2. 對于UI : 盡量避免使用Unity3D自帶的 GUI 換用 NGUI或者EZGUI烫扼;因為這兩個UI插件對于UI中的圖片處理是將UI圖片放置在一個 Atlas中,一個 Atlas 對應(yīng)一個Drawcall
57碍庵、 3. 對于燈光: 可以使用 Unity3D 自帶的 Lightmapping插件來烘焙場景中的燈光效果到物體材質(zhì)上
58映企、 4. 對于場景: 可以使用 Unity3D 自帶的 OcclusionCulling 插件把靜止不動的場景元素烘焙出來
59、 4. 對于特效:盡量把材質(zhì)紋理合并
60静浴、 對于Unity3D 在移動終端上支持的Drawcall
數(shù)到底多少堰氓,主要是跟機(jī)子性能有關(guān)的,當(dāng)然也不是說值小性能就一定沒問題(本人親測苹享,也有17就卡的双絮,主要是模型材質(zhì)紋理過大所引起的),目前我做的是70左右的得问,還OK囤攀,挺正常的
61、
62宫纬、 由于點焚挠、面過多所導(dǎo)致的性能問題,最好用簡模漓骚,用四面體來做復(fù)雜的模型蝌衔,但是面、點也別太多认境,至于Unity3D 到底支持多少點胚委、面的說法各異,我也搞不懂叉信,總之少些肯定OK
63亩冬、
64、
65、
66硅急、 檢測方式:
67覆享、 一,Unity3D 渲染統(tǒng)計窗口
68营袜、 Game視窗的Stats去查看渲染統(tǒng)計的信息:
69撒顿、 1、FPS
70荚板、 fps其實就是 framesper second,也就是每一秒游戲執(zhí)行的幀數(shù)凤壁,這個數(shù)值越小,說明游戲越卡跪另。
71拧抖、
72、 2免绿、Draw calls
73唧席、 batching之后渲染mesh的數(shù)量,和當(dāng)前渲染到的網(wǎng)格的材質(zhì)球數(shù)量有關(guān)嘲驾。
74淌哟、
75、 3辽故、Saved by batching
76徒仓、 渲染的批處理數(shù)量,這是引擎將多個對象的繪制進(jìn)行合并從而減少GPU的開銷;
77榕暇、 很多GUI插件的一個好處就是合并多個對象的渲染蓬衡,從而降低DrawCalls 喻杈,保證游戲幀數(shù)彤枢。
78、
79筒饰、 4缴啡、Tris 當(dāng)前繪制的三角面數(shù)
80、
81瓷们、 5业栅、Verts 當(dāng)前繪制的頂點數(shù)
82、
83谬晕、 6碘裕、Used Textures 當(dāng)前幀用于渲染的圖片占用內(nèi)存大小
84、
85攒钳、 7帮孔、Render Textures 渲染的圖片占用內(nèi)存大小,也就是當(dāng)然渲染的物體的材質(zhì)上的紋理總內(nèi)存占用
86、
87文兢、 8晤斩、VRAM usage 顯存的使用情況,VRAM總大小取決于你的顯卡的顯存
88姆坚、
89澳泵、 9、VBO Total 渲染過程中上載到圖形卡的網(wǎng)格的數(shù)量兼呵,這里注意一點就是縮放的物體可能需要額外的開銷兔辅。
90、
91击喂、 10幢妄、VisibleSkinned Meshes 蒙皮網(wǎng)格的渲染數(shù)量
92、
93茫负、 11蕉鸳、Animations 播放動畫的數(shù)量
94、 注意事項:
95忍法、 1,運行時盡量減少 Tris 和 Draw Calls
96潮尝、 預(yù)覽的時候,可點開 Stats饿序,查看圖形渲染的開銷情況勉失。特別注意 Tris 和 Draw Calls 這兩個參數(shù)。
97原探、 一般來說乱凿,要做到:
98、 Tris 保持在 7.5k 以下咽弦,有待考證徒蟆。
99、 Draw Calls 保持在 20 以下型型,有待考證段审。
100、 2闹蒜,F(xiàn)PS寺枉,每一秒游戲執(zhí)行的幀數(shù),這個數(shù)值越小绷落,說明游戲越卡姥闪。
101、 3砌烁,Render Textures 渲染的圖片占用內(nèi)存大小筐喳。
102、 4,VRAM usage 顯存的使用情況疏唾,VRAM總大小取決于你的顯卡的顯存蓄氧。
103、
104槐脏、 二喉童,代碼優(yōu)化
105、 1. 盡量避免每幀處理
106顿天、 比如:
107堂氯、 function Update() {DoSomeThing(); }
108、 可改為每5幀處理一次:
109牌废、 function Update() { if(Time.frameCount% 5 == 0) { DoSomeThing(); } }
110咽白、 2. 定時重復(fù)處理用InvokeRepeating 函數(shù)實現(xiàn)
111、 比如鸟缕,啟動0.5秒后每隔1秒執(zhí)行一次 DoSomeThing 函數(shù):
112晶框、
113、 function Start() {InvokeRepeating("DoSomeThing", 0.5, 1.0); }
114懂从、
115授段、 3. 優(yōu)化 Update,FixedUpdate, LateUpdate 等每幀處理的函數(shù)
116、 函數(shù)里面的變量盡量在頭部聲明番甩。
117侵贵、 比如:
118、 function Update() { var pos:Vector3 = transform.position; }
119缘薛、 可改為
120窍育、 private var pos: Vector3;function Update(){ pos = transform.position; }
121、
122宴胧、 4. 主動回收垃圾
123漱抓、 給某個 GameObject 綁上以下的代碼:
124、 function Update() {if(Time.frameCount % 50 == 0) { System.GC.Collect(); } }
125牺汤、
126辽旋、 5. 優(yōu)化數(shù)學(xué)計算
127浩嫌、 比如檐迟,如果可以避免使用浮點型(float),盡量使用整形(int)码耐,盡量少用復(fù)雜的數(shù)學(xué)函數(shù)比如 Sin 和 Cos 等等
128追迟、
129、 6骚腥,減少固定增量時間
130敦间、 將固定增量時間值設(shè)定在0.04-0.067區(qū)間(即,每秒15-25幀)。您可以通過Edit->Project
Settings->Time來改變這個值廓块。這樣做降低了FixedUpdate函數(shù)被調(diào)用的頻率以及物理引擎執(zhí)行碰撞檢測與剛體更新的頻率厢绝。如果您使用了較低的固定增量時間,并且在主角身上使用了剛體部件带猴,那么您可以啟用插值辦法來平滑剛體組件昔汉。
131、 7拴清,減少GetComponent的調(diào)用
132靶病、 使用 GetComponent或內(nèi)置組件訪問器會產(chǎn)生明顯的開銷。您可以通過一次獲取組件的引用來避免開銷口予,并將該引用分配給一個變量(有時稱為"緩存"的引用)娄周。例如,如果您使用如下的代碼:
133沪停、 function Update () {
134煤辨、 transform.Translate(0, 1, 0);
135、
136木张、 }
137掷酗、 通過下面的更改您將獲得更好的性能:
138、
139窟哺、 var myTransform : Transform;
140泻轰、 function Awake () {
141、 myTransform = transform;
142且轨、 }
143浮声、 function Update () {
144、 myTransform.Translate(0, 1, 0);
145旋奢、 }
146泳挥、
147、 8至朗,避免分配內(nèi)存
148屉符、 您應(yīng)該避免分配新對象,除非你真的需要锹引,因為他們不再在使用時矗钟,會增加垃圾回收系統(tǒng)的開銷。您可以經(jīng)常重復(fù)使用數(shù)組和其他對象嫌变,而不是分配新的數(shù)組或?qū)ο蠖滞А_@樣做好處則是盡量減少垃圾的回收工作。同時腾啥,在某些可能的情況下东涡,您也可以使用結(jié)構(gòu)(struct)來代替類(class)冯吓。這是因為,結(jié)構(gòu)變量主要存放在棧區(qū)而非堆區(qū)疮跑。因為棧的分配較快组贺,并且不調(diào)用垃圾回收操作,所以當(dāng)結(jié)構(gòu)變量比較小時可以提升程序的運行性能祖娘。但是當(dāng)結(jié)構(gòu)體較大時锣披,雖然它仍可避免分配/回收的開銷,而它由于"傳值"操作也會導(dǎo)致單獨的開銷贿条,實際上它可能比等效對象類的效率還要低雹仿。
149、
150整以、 9胧辽,使用iOS腳本調(diào)用優(yōu)化功能
151、 UnityEngine 命名空間中的函數(shù)的大多數(shù)是在 C/c + +中實現(xiàn)的公黑。從Mono的腳本調(diào)用
C/C++函數(shù)也存在著一定的性能開銷邑商。您可以使用iOS腳本調(diào)用優(yōu)化功能(菜單:Edit->Project
Settings->Player)讓每幀節(jié)省1-4毫秒。此設(shè)置的選項有:
152凡蚜、 Slow and Safe – Mono內(nèi)部默認(rèn)的處理異常的調(diào)用
153人断、
154、 Fast and Exceptions Unsupported–一個快速執(zhí)行的Mono內(nèi)部調(diào)用朝蜘。不過恶迈,它并不支持異常,因此應(yīng)謹(jǐn)慎使用谱醇。它對于不需要顯式地處理異常(也不需要對異常進(jìn)行處理)的應(yīng)用程序來說暇仲,是一個理想的候選項。
155副渴、
156奈附、 10,
157煮剧、 優(yōu)化垃圾回收
158斥滤、
159、 如上文所述勉盅,您應(yīng)該盡量避免分配操作佑颇。但是,考慮到它們是不能完全杜絕的菇篡,所以我們提供兩種方法來讓您盡量減少它們在游戲運行時的使用:
160漩符、 如果堆比較小,則進(jìn)行快速而頻繁的垃圾回收
161驱还、 這一策略比較適合運行時間較長的游戲嗜暴,其中幀率是否平滑過渡是主要的考慮因素。像這樣的游戲通常會頻繁地分配小塊內(nèi)存议蟆,但這些小塊內(nèi)存只是暫時地被使用闷沥。如果在iOS系統(tǒng)上使用該策略,那么一個典型的堆大小是大約
200 KB咐容,這樣在iPhone 3G設(shè)備上舆逃,垃圾回收操作將耗時大約 5毫秒。如果堆大小增加到1 MB時戳粒,該回收操作將耗時大約
7ms路狮。因此,在普通幀的間隔期進(jìn)行垃圾回收有時候是一個不錯的選擇蔚约。通常奄妨,這種做法會讓回收操作執(zhí)行的更加頻繁(有些回收操作并不是嚴(yán)格必須進(jìn)行的),但它們可以快速處理并且對游戲的影響很衅凰睢:
162砸抛、 if (Time.frameCount % 30 == 0)
163、 {
164树枫、 System.GC.Collect();
165直焙、 }
166、
167砂轻、 但是奔誓,您應(yīng)該小心地使用這種技術(shù),并且通過檢查Profiler來確保這種操作確實可以降低您游戲的垃圾回收時間
168搔涝、 如果堆比較大丝里,則進(jìn)行緩慢且不頻繁的垃圾回收
169、 這一策略適合于那些內(nèi)存分配
(和回收)相對不頻繁体谒,并且可以在游戲停頓期間進(jìn)行處理的游戲杯聚。如果堆足夠大,但還沒有大到被系統(tǒng)關(guān)掉的話抒痒,這種方法是比較適用的幌绍。但是,Mono運行時會盡可能地避免堆的自動擴(kuò)大故响。因此傀广,您需要通過在啟動過程中預(yù)分配一些空間來手動擴(kuò)展堆(ie,你實例化一個純粹影響內(nèi)存管理器分配的"無用"對象):
170彩届、
171伪冰、 function Start() {
172、
173樟蠕、 var tmp = newSystem.Object[1024];
174贮聂、
175靠柑、 // make allocations in smallerblocks to avoid them to
be treated in a special way, which is designed forlarge blocks
176、
177吓懈、 for (var i : int = 0; i <1024; i++)
178歼冰、
179、 tmp[i] = new byte[1024];
180耻警、
181隔嫡、 // release reference
182、
183甘穿、 tmp = null;
184腮恩、
185、 }
186温兼、
187秸滴、 游戲中的暫停是用來對堆內(nèi)存進(jìn)行回收,而一個足夠大的堆應(yīng)該不會在游戲的暫停與暫停之間被完全占滿妨托。所以缸榛,當(dāng)這種游戲暫停發(fā)生時,您可以顯式請求一次垃圾回收:
188兰伤、
189内颗、 System.GC.Collect();
190、
191敦腔、 另外均澳,您應(yīng)該謹(jǐn)慎地使用這一策略并時刻關(guān)注Profiler的統(tǒng)計結(jié)果,而不是假定它已經(jīng)達(dá)到了您想要的效果符衔。
192找前、
193、 三判族,模型
194躺盛、 1,壓縮 Mesh
195、 導(dǎo)入 3D 模型之后形帮,在不影響顯示效果的前提下槽惫,最好打開 Mesh Compression。
196辩撑、 Off, Low, Medium, High 這幾個選項界斜,可酌情選取。
197合冀、 2,避免大量使用 Unity 自帶的 Sphere 等內(nèi)建 Mesh
198各薇、 Unity 內(nèi)建的 Mesh,多邊形的數(shù)量比較大君躺,如果物體不要求特別圓滑峭判,可導(dǎo)入其他的簡單3D模型代替开缎。
199、
200朝抖、 1不是每個主流手機(jī)都支持的技術(shù)(就是如果可以不用就不用或有備選方案)
201啥箭、 屏幕特效
202谍珊、 動態(tài)的pixel光照計算(如法線)
203治宣、 實時的陰影
204、
205砌滞、 2優(yōu)化建議
206侮邀、 2.1渲染
207、 1.不使用或少使用動態(tài)光照贝润,使用light mapping和light probes(光照探頭)
208绊茧、 2.不使用法線貼圖(或者只在主角身上使用),靜態(tài)物體盡量將法線渲染到貼圖
209打掘、 3.不適用稠密的粒子华畏,盡量使用UV動畫
210尊蚁、 4.不使用fog横朋,使用漸變的面片(參考shadowgun)
211仑乌、 5.不要使用alpha–test(如那些cutout shader),使用alpha-blend代替
212琴锭、 6.使用盡量少的material晰甚,使用盡量少的pass和render次數(shù)厕九,如反射地回、陰影這些操作
213扁远、 7.如有必要,使用Per-LayerCull Distances落君,Camera.layerCullDistances
214、 8.只使用mobile組里面的那些預(yù)置shader
215绎速、 9.使用occlusionculling
216皮获、 11.遠(yuǎn)處的物體繪制在skybox上
217、 12.使用drawcallbatching:
218纹冤、 對于相鄰動態(tài)物體:如果使用相同的shader洒宝,將texture合并
219购公、 對于靜態(tài)物體,batching要求很高雁歌,詳見Unity Manual>Advanced>Optimizing
Graphics Performance>Draw
Call Batching
220宏浩、
221、 規(guī)格上限
222靠瞎、 1. 每個模型只使用一個skinnedmesh renderer
223比庄、 2. 每個mesh不要超過3個material
224佳窑、 3. 骨骼數(shù)量不要超過30
225、 4. 面數(shù)在1500以內(nèi)將得到好的效率
226父能、 2.2物理
227神凑、 1.真實的物理(剛體)很消耗,不要輕易使用瓣喊,盡量使用自己的代碼模仿假的物理
228呆细、 2.對于投射物不要使用真實物理的碰撞和剛體型宝,用自己的代碼處理
229、 3.不要使用meshcollider
230絮爷、 4.在edit->projectsetting->time中調(diào)大FixedTimestep(真實物理的幀率)來減少cpu損耗
231趴酣、 2.3腳本編寫
232、 1.盡量不要動態(tài)的instantiate和destroyobject坑夯,使用object pool
233岖寞、 2.盡量不要再update函數(shù)中做復(fù)雜計算,如有需要柜蜈,可以隔N幀計算一次
234仗谆、 3.不要動態(tài)的產(chǎn)生字符串,如Debug.Log("boo"+ "hoo")淑履,盡量預(yù)先創(chuàng)建好這些字符串資源
235隶垮、 4.cache一些東西恒削,在update里面盡量避免search择份,如GameObject.FindWithTag("")、GetComponent這樣的調(diào)用盼铁,可以在start中預(yù)先存起來
236、 5.盡量減少函數(shù)調(diào)用棧蹋偏,用x= (x > 0 ? x : -x);代替x = Mathf.Abs(x)
237便斥、 6.下面的代碼是幾個gc“噩夢”
238、 String的相加操作威始,會頻繁申請內(nèi)存并釋放枢纠,導(dǎo)致gc頻繁,使用System.Text.StringBuilder代替
239黎棠、 functionConcatExample(intArray: int[]) {
240晋渺、 varline = intArray[0].ToString();
241、
242葫掉、 for(i = 1; i < intArray.Length; i++) {
243些举、 line+= ", " + intArray[i].ToString();
244跟狱、 }
245俭厚、
246、 returnline;
247驶臊、 }
248挪挤、 在函數(shù)中動態(tài)new array,最好將一個array关翎、傳進(jìn)函數(shù)里修改
249扛门、 functionRandomList(numElements: int) {
250、 varresult = new float[numElements];
251纵寝、
252论寨、 for(i = 0; i < numElements; i++) {
253、 result[i]= Random.value;
254爽茴、 }
255葬凳、
256、 returnresult;
257室奏、 }
258火焰、
259、 2.4 shader編寫
260胧沫、 1.數(shù)據(jù)類型
261昌简、 fixed / lowp -for colors, lighting information and normals,
262、 half / mediump -for texture UV coordinates,
263绒怨、 float / highp -avoid in pixel shaders, fine to use in vertex shader for position calculations.
264纯赎、 2.少使用的函數(shù):pow,sin,cos等
265、 2.4 GUI
266南蹂、 1.不要使用內(nèi)置的onGUii函數(shù)處理gui犬金,使用其他方案,如NGUI
267、
268佑附、 3.格式
269樊诺、 1.貼圖壓縮格式:ios上盡量使用PVRTC,android上使用ETC
270音同、 最簡單的優(yōu)化建議:
1.PC平臺的話保持場景中顯示的頂點數(shù)少于200K~3M词爬,移動設(shè)備的話少于10W,一切取決于你的目標(biāo)GPU與CPU权均。
2.如果你用U3D自帶的SHADER顿膨,在表現(xiàn)不差的情況下選擇Mobile或Unlit目錄下的。它們更高效叽赊。
3.盡可能共用材質(zhì)恋沃。
4.將不需要移動的物體設(shè)為Static,讓引擎可以進(jìn)行其批處理必指。
5.盡可能不用燈光囊咏。
6.動態(tài)燈光更加不要了。
7.嘗試用壓縮貼圖格式塔橡,或用16位代替32位梅割。
8.如果不需要別用霧效(fog)
9.嘗試用OcclusionCulling,在房間過道多遮擋物體多的場景非常有用。若不當(dāng)反而會增加負(fù)擔(dān)葛家。
10.用天空盒去“褪去”遠(yuǎn)處的物體户辞。
11.shader中用貼圖混合的方式去代替多重通道計算。
12.shader中注意float/half/fixed的使用癞谒。
13.shader中不要用復(fù)雜的計算pow,sin,cos,tan,log等底燎。
14.shader中越少Fragment越好。
15.注意是否有多余的動畫腳本弹砚,模型自動導(dǎo)入到U3D會有動畫腳本双仍,大量的話會嚴(yán)重影響消耗CPU計算。
16.注意碰撞體的碰撞層迅栅,不必要的碰撞檢測請舍去殊校。
1.為什么需要針對CPU(中央處理器)與GPU(圖形處理器)優(yōu)化?
CPU和GPU都有各自的計算和傳輸瓶頸读存,不同的CPU或GPU他們的性能都不一樣为流,所以你的游戲需要為你目標(biāo)用戶的CPU與GPU能力進(jìn)行針對開發(fā)。
2.CPU與GPU的限制
GPU一般具有填充率(Fillrate)和內(nèi)存帶寬(Memory Bandwidth)的限制让簿,如果你的游戲在低質(zhì)量表現(xiàn)的情況下會快很多敬察,那么,你很可能需要限制你在GPU的填充率尔当。
CPU一般被所需要渲染物體的個數(shù)限制莲祸,CPU給GPU發(fā)送渲染物體命令叫做DrawCalls蹂安。一般來說DrawCalls數(shù)量是需要控制的,在能表現(xiàn)效果的前提下越少越好锐帜。通常來說田盈,電腦平臺上DrawCalls幾千個之內(nèi),移動平臺上DrawCalls幾百個之內(nèi)缴阎。這樣就差不多了允瞧。當(dāng)然以上并不是絕對的,僅作一個參考蛮拔。
往往渲染(Rendering)并不是一個問題述暂,無論是在GPU和CPU上。很可能是你的腳本代碼效率的問題建炫,用Profiler查看下畦韭。
關(guān)于Profiler介紹:http://docs.unity3d.com/Documentation/Manual/Profiler.html
需要注意的是:
在GPU中顯示的RenderTexture.SetActive()占用率很高,是因為你同時打開了編輯窗口的原因肛跌,而不是U3D的BUG艺配。
3.關(guān)于頂點數(shù)量和頂點計算
CPU和GPU對頂點的計算處理都很多。GPU中渲染的頂點數(shù)取決于GPU性能和SHADER的復(fù)雜程度惋砂,一般來說妒挎,每幀之內(nèi),在PC上幾百萬頂點內(nèi)西饵,在移動平臺上不超過10萬頂點。
CPU中的計算主要是在蒙皮骨骼計算鳞芙,布料模擬眷柔,頂點動畫,粒子模擬等原朝。GPU則在各種頂點變換驯嘱、光照、貼圖混合等喳坠。
【個人認(rèn)為鞠评,具體還是看各位的項目需求,假設(shè)你項目的是3d游戲壕鹉。你游戲需要兼容低配置的硬件剃幌、流暢運行、控制硬件發(fā)熱的話晾浴,還要達(dá)到一定效果(LIGHTMAP+霧效)负乡,那么頂點數(shù)必定不能高。此時同屏2W頂點我認(rèn)為是個比較合適的數(shù)目脊凰,DRAWCALL最好低于70抖棘。另,控制發(fā)熱請控制最高上限的幀率,流暢的話切省,幀率其實不需要太高的最岗。】
4.針對CPU的優(yōu)化——減少DRAW CALL 的數(shù)量
為了渲染物體到顯示器上朝捆,CPU需要做一些工作,如區(qū)分哪個東西需要渲染仑性、區(qū)分開物體是否受光照影響、使用哪個SHADER并且為SHADER傳參右蹦、發(fā)送繪圖命令告訴顯示驅(qū)動诊杆,然后發(fā)送命令告訴顯卡刪除等這些。
假設(shè)你有一個上千三角面的模型卻用上千個三角型模型來代替何陆,在GPU上花費是差不多的晨汹,但是在CPU上則是極其不一樣,消耗會大很多很多贷盲。為了讓CPU更少的工作淘这,需要減少可見物的數(shù)目:
a.合并相近的模型,手動在模型編輯器中合并或者使用UNITY的Draw call批處理達(dá)到相同效果(Draw call batching)巩剖。具體方法和注意事項查看以下鏈接:
Draw call batching :http://docs.unity3d.com/Documentation/Manual/DrawCallBatching.html
b.在項目中使用更少的材質(zhì)(material)铝穷,將幾個分開的貼圖合成一個較大的圖集等方式處理。
如果你需要通過腳本來控制單個材質(zhì)屬性佳魔,需要注意改變Renderer.material將會造成一份材質(zhì)的拷貝曙聂。因此,你應(yīng)該使用Renderer.sharedMaterial來保證材質(zhì)的共享狀態(tài)鞠鲜。
有一個合并模型材質(zhì)不錯的插件叫Mesh Baker宁脊,大家可以考慮試下。
c.盡量少用一些渲染步驟贤姆,例如reflections,shadows,per-pixel light 等榆苞。
d.Draw call batching的合并物體,會使每個物體(合并后的物體)至少有幾百個三角面霞捡。
假設(shè)合并的兩個物體(手動合并)但不共享材質(zhì)坐漏,不會有性能表現(xiàn)上的提升。多材質(zhì)的物體相當(dāng)于兩個物體不用一個貼圖碧信。所以赊琳,為了提升CPU的性能,你應(yīng)該確保這些物體使用同樣的貼圖音婶。
另外慨畸,用燈光將會取消(break)引擎的DRAW CALL BATCH,至于為什么衣式,查看以下:
Forward Rendering Path Details:
http://docs.unity3d.com/Documentation/Components/RenderTech-ForwardRendering.html
e.使用相關(guān)剔除數(shù)量直接減少Draw Call數(shù)量寸士,下文有相關(guān)提及檐什。
5.優(yōu)化幾何模型
最基本的兩個優(yōu)化準(zhǔn)則:
a.不要有不必要的三角面。
b.UV貼圖中的接縫和硬邊越少越好弱卡。
需要注意的是乃正,圖形硬件需要處理頂點數(shù)并跟硬件報告說的并不一樣。不是硬件說能渲染幾個點就是幾個點婶博。模型處理應(yīng)用通展示的是幾何頂點數(shù)量瓮具。例如,一個由一些不同頂點構(gòu)成的模型凡人。在顯卡中名党,一些集合頂點將會被分離(split)成兩個或者更多邏輯頂點用作渲染。如果有法線挠轴、UV坐標(biāo)传睹、頂點色的話,這個頂點必須會被分離岸晦。所以在游戲中處理的實際數(shù)量顯然要多很多欧啤。
6.關(guān)于光照
若不用光肯定是最快的。移動端優(yōu)化可以采用用光照貼圖(Lightmapping)去烘培一個靜態(tài)的貼圖启上,以代替每次的光照計算邢隧,在U3D中只需要非常短的時間則能生成。這個方法能大大提高效率冈在,而且有著更好的表現(xiàn)效果(平滑過渡處理倒慧,還有附加陰影等)。
在移動設(shè)備上和低端電腦上盡量不要在場景中用真光讥邻,用光照貼圖迫靖。這個方法大大節(jié)省了CPU和GPU的計算,CPU得到了更少的DRAWCALL兴使,GPU則需要更少頂點處理和像素柵格化。
Lightmapping : http://docs.unity3d.com/Documentation/Manual/Lightmapping.html
7.對GPU的優(yōu)化——圖片壓縮和多重紋理格式
Compressed Textures(圖片壓縮):
http://docs.unity3d.com/Documentation/Components/class-Texture2D.html
圖片壓縮將降低你的圖片大姓占ぁ(更快地加載更小的內(nèi)存跨度(footprint))发魄,而且大大提高渲染表現(xiàn)。壓縮貼圖比起未壓縮的32位RGBA貼圖占用內(nèi)存帶寬少得多俩垃。
之前U3D會議還聽說過一個優(yōu)化励幼,貼圖盡量都用一個大小的格式(512 * 512 , 1024 * 1024)口柳,這樣在內(nèi)存之中能得到更好的排序苹粟,而不會有內(nèi)存之間空隙。這個是否真假沒得到過測試跃闹。
MIPMAps(多重紋理格式):
http://docs.unity3d.com/Documentation/Components/class-Texture2D.html
跟網(wǎng)頁上的略縮圖原理一樣嵌削,在3D游戲中我們?yōu)橛螒虻馁N圖生成多重紋理貼圖毛好,遠(yuǎn)處顯示較小的物體用小的貼圖,顯示比較大的物體用精細(xì)的貼圖苛秕。這樣能更加有效的減少傳輸給GPU中的數(shù)據(jù)肌访。
8.LOD 、 Per-Layer Cull Distances 艇劫、 Occlusion Culling
LOD (Level Of Detail) 是很常用的3D游戲技術(shù)了吼驶,其功能理解起來則是相當(dāng)于多重紋理貼圖。在以在屏幕中顯示模型大小的比例來判斷使用高或低層次的模型來減少對GPU的傳輸數(shù)據(jù)店煞,和減少GPU所需要的頂點計算蟹演。
攝像機(jī)分層距離剔除(Per-Layer Cull Distances):為小物體標(biāo)識層次,然后根據(jù)其距離主攝像機(jī)的距離判斷是否需要顯示顷蟀。
遮擋剔除(Occlusion Culling)其實就是當(dāng)某個物體在攝像機(jī)前被另外一個物體完全擋住的情況酒请,擋住就不發(fā)送給GPU渲染,從而直接降低DRAW CALL衩椒。不過有些時候在CPU中計算其是否被擋住則會很耗計算蚌父,反而得不償失。
以下是這幾個優(yōu)化技術(shù)的相關(guān)使用和介紹:
Level Of Detail :
http://docs.unity3d.com/Documentation/Manual/LevelOfDetail.html
Per-Layer Cull Distances :
http://docs.unity3d.com/Documentation/ScriptReference/Camera-layerCullDistances.html
Occlusion Culling :
http://docs.unity3d.com/Documentation/Manual/OcclusionCulling.html
9.關(guān)于Realtime Shadows(實時陰影)
實時陰影技術(shù)非常棒毛萌,但消耗大量計算苟弛。為GPU和CPU都帶來了昂貴的負(fù)擔(dān),細(xì)節(jié)的話參考下面:
http://docs.unity3d.com/Documentation/Manual/Shadows.html
10.對GPU優(yōu)化:采用高效的shader
a.需要注意的是有些(built-in)Shader是有mobile版本的阁将,這些大大提高了頂點處理的性能膏秫。當(dāng)然也會有一些限制。
b.自己寫的shader請注意復(fù)雜操作符計算做盅,類似pow,exp,log,cos,sin,tan等都是很耗時的計算缤削,最多只用一次在每個像素點的計算。不推薦你自己寫normalize,dot,inversesqart操作符吹榴,內(nèi)置的肯定比你寫的好亭敢。
c.需要警醒的是alpha test,這個非常耗時图筹。
d.浮點類型運算:精度越低的浮點計算越快帅刀。
在CG/HLSL中--
float :32位浮點格式,適合頂點變換運算远剩,但比較慢扣溺。
half:16位浮點格式,適合貼圖和UV坐標(biāo)計算瓜晤,是highp類型計算的兩倍锥余。
fixed: 10位浮點格式,適合顏色痢掠,光照驱犹,和其他嘲恍。是highp格式計算的四倍。
寫Shader優(yōu)化的小提示:
http://docs.unity3d.com/Documentation/Components/SL-ShaderPerformance.html
11.另外的相關(guān)優(yōu)化:
a.對Draw Call Batching的優(yōu)化
http://docs.unity3d.com/Documentation/Manual/DrawCallBatching.html
b.對Rendering Statistics Window的說明和提示:
http://docs.unity3d.com/Documentation/Manual/RenderingStatistics.html
c.角色模型的優(yōu)化建議
用單個蒙皮渲染着绷、盡量少用材質(zhì)蛔钙、少用骨骼節(jié)點、移動設(shè)備上角色多邊形保持在3001500內(nèi)(當(dāng)然還要看具體的需求)荠医、PC平臺上15004000內(nèi)(當(dāng)然還要看具體的需求)吁脱。
http://docs.unity3d.com/Documentation/Manual/ModelingOptimizedCharacters.html
渲染順序
U3D的渲染是有順序的,U3D的渲染順序是由我們控制的彬向,控制好U3D的渲染順序兼贡,你才能控制好DrawCall
一個DrawCall,表示U3D使用這個材質(zhì)/紋理娃胆,來進(jìn)行一次渲染遍希,那么這次渲染假設(shè)有3個對象,那么當(dāng)3個對象都使用這一個材質(zhì)/紋理的
時候里烦,就會產(chǎn)生一次DrawCall凿蒜,可以理解為一次將紋理輸送到屏幕上的過程,(實際上引擎大多會使用如雙緩沖胁黑,緩存這類的手段來優(yōu)化這個過程废封,但在這
里我們只需要這樣子認(rèn)識就可以了),假設(shè)3個對象使用不同的材質(zhì)/紋理丧蘸,那么無疑會產(chǎn)生3個DrawCall
接下來我們的3個對象使用2個材質(zhì)漂洋,A和B使用材質(zhì)1,C使用材質(zhì)2力喷,這時候來看刽漂,應(yīng)該是有2個DrawCall,或者3個DrawCall弟孟。
應(yīng)該是2個DrawCall啊贝咙,為什么會有3個DrawCall?拂募?颈畸?而且是有時候2個,有時候3個没讲。我們按照上面的DrawCall分析流程來分析一
下:
1.渲染A,使用材質(zhì)1
2.渲染B礁苗,使用材質(zhì)1
3.渲染C爬凑,使用材質(zhì)2
在這種情況下是2個DrawCall,在下面這種情況下试伙,則是3個DrawCall
1.渲染A嘁信,使用材質(zhì)1
2.渲染C于样,使用材質(zhì)2
3.渲染B,使用材質(zhì)1
因為我們沒有控制好渲染順序(或者說沒有去特意控制)潘靖,所以導(dǎo)致了額外的DrawCall穿剖,因為A和B不是一次性渲染完的,而是被C打斷了卦溢,所以導(dǎo)致材質(zhì)1被分為兩次渲染
那么是什么在控制這個渲染順序呢糊余?首先在多個相機(jī)的情況下,U3D會根據(jù)相機(jī)的深度順序進(jìn)行渲染单寂,在每個相機(jī)中贬芥,它會根據(jù)你距離相機(jī)的距離,由遠(yuǎn)到近進(jìn)行渲染宣决,在UI相機(jī)中蘸劈,還會根據(jù)你UI對象的深度進(jìn)行渲染
那么我們要做的就是,對要渲染的對象進(jìn)行一次規(guī)劃尊沸,正確地排列好它們威沫,規(guī)則是,按照Z軸或者深度洼专,對空間進(jìn)行劃分棒掠,然后確定好每個對象的Z軸和深度,讓使用同一個材質(zhì)的東西壶熏,盡量保持在這個空間內(nèi)句柠,不要讓其他材質(zhì)的對象進(jìn)入這個空間,否則就會打斷這個空間的渲染順序
在這個基礎(chǔ)上棒假,更細(xì)的規(guī)則有:
場景中的東西溯职,我們使用Z軸來進(jìn)行空間的劃分,例如背景層帽哑,特效層1谜酒,人物層,特效層2
NGUI中的東西妻枕,我們統(tǒng)一使用Depth來進(jìn)行空間的劃分
人物模型僻族,當(dāng)人物模型只是用一個材質(zhì),DrawCall只有1屡谐,但是用了2個以上的材質(zhì)述么,DrawCall就會暴增(或許對材質(zhì)的RenderQueue
進(jìn)行規(guī)劃也可以使DrawCall只有2個,但這個要拆分好才行)愕掏,3D人物處于復(fù)雜3D場景中的時候度秘,我們的空間規(guī)則難免被破壞,這只能在設(shè)計的時候盡
量去避免這種情況了
使用了多個材質(zhì)的特效饵撑,在動畫的過程中剑梳,往往會引起DrawCall的波動唆貌,在視覺效果可以接受的范圍內(nèi),可以將特效也進(jìn)行空間劃分垢乙,假設(shè)這個特效是2D顯示锨咙,那么可以使用Z軸來劃分空間