前言
做手機(jī)游戲開發(fā)的時(shí),經(jīng)常會(huì)遇到手機(jī)游戲的性能問題,手機(jī)游戲的性能問題可能有很多的方面,今天我們從CPU調(diào)優(yōu)的角度來給大家介紹一下常用的CPU調(diào)優(yōu)的一些經(jīng)驗(yàn)和手段。這些經(jīng)驗(yàn)和手段都有可能隨著時(shí)間與環(huán)境的變化改變而改變溃蔫,具體還是要以實(shí)際的為準(zhǔn)皆疹,先定位性能問題闽铐,再上具體的手段蝶怔。接下來我們從CPU的性能調(diào)優(yōu)的角度來總結(jié)一下Unity手游開發(fā)中需要注意和優(yōu)化CPU的一些點(diǎn)。我們把手機(jī)游戲的CPU調(diào)優(yōu)分成幾個(gè)模塊兄墅,列舉一下每個(gè)模塊的一些經(jīng)驗(yàn)踢星,供大家參考。模塊如下:
對(duì)惹隙咸,這里有一個(gè)游戲開發(fā)交流小組沐悦,希望大家可以點(diǎn)擊進(jìn)來一起交流一下開發(fā)經(jīng)驗(yàn)呀
(1) 渲染模塊;
(2) 物理模塊;
(3) 動(dòng)畫模塊與粒子系統(tǒng);
(4) 邏輯代碼優(yōu)化
渲染模塊調(diào)優(yōu)
影響渲染CPU執(zhí)行效率的本質(zhì)就是兩個(gè)東西,一個(gè)是渲染的面數(shù)(Triangle), 一個(gè)是渲染提交的次數(shù)(Drawcall)五督。這個(gè)部分很多開發(fā)者就會(huì)陷入一個(gè)所謂的標(biāo)準(zhǔn)”手機(jī)上模型一般多少個(gè)面合適藏否?”這種問題其實(shí)沒有任何意義的,需要結(jié)合自己的游戲來進(jìn)行實(shí)測(cè)充包。時(shí)空背景不一樣副签,游戲玩法不一樣結(jié)果就不一樣。一般我們的做法就是到自己目標(biāo)客戶的機(jī)型上進(jìn)行實(shí)測(cè)基矮。在我們的Shader確定后的效果下淆储,我們目標(biāo)客戶的機(jī)型上面能跑多少個(gè)面。然后我們結(jié)合游戲的玩法家浇,這些面放在哪些地方本砰。比如近距離我們的面就分配得多,遠(yuǎn)距離就分配得少蓝谨。重要主角面分配得多灌具,不重要物體的面分配得少青团。也可以通過LOD工具在低端手機(jī)上減少模型面數(shù)譬巫。Drawcall大家比較熟悉了,有動(dòng)態(tài)合批督笆,靜態(tài)合批芦昔,SRP Batcher合批,GPU Instancing合批,具體可以參考教程《Unity 如何優(yōu)化Drawcall》。還有一個(gè)被很多人忽視的就是Set Pass Call開銷娃肿,在這個(gè)過程中咕缎,第一次加載Shader容易造成瞬間卡頓。Shader.CreateGPUProgram, 解決的方案是運(yùn)行的時(shí)候做好Shader緩存料扰,避免瞬間CPU卡頓凭豪。
在UGUI的優(yōu)化中,主要是檢查UI的邏輯響應(yīng)函數(shù)是否占用過高晒杈,同時(shí)把不用事件響應(yīng)的UI元素去掉選項(xiàng)”Raycast Target”, 這樣不用在每個(gè)UI元素去檢測(cè)用戶是否有UI操作嫂伞,減少EventSystem.Update()耗時(shí)開銷。每個(gè)Canvas會(huì)調(diào)用BuildBatch為UI元素合并的Mesh。一旦UI元素發(fā)起移動(dòng)帖努,這樣就會(huì)引發(fā)BuildBatch, 合并過程是在其它線程處理的撰豺,如果合并的消耗過大,就會(huì)導(dǎo)致主線程發(fā)起等待拼余。這個(gè)是我們我們可以把靜態(tài)的物體分到一個(gè)Canvas,動(dòng)態(tài)的物體分到一個(gè)Canvas,這樣污桦,能降低合并的難度與合并的開銷。UGUI的使用過程中也注意以下幾個(gè)點(diǎn):
(1)同一Canvas下的UI元素才能合批匙监。不同Canvas即使Order in Layer相同也不合批凡橱;
(2)盡量使用圖集,讓UI Drawcall合并有可能;
(3)在同一Canvas下亭姥、且材質(zhì)和圖集一致的前提下梭纹,盡量把同一個(gè)圖集的節(jié)點(diǎn)放一起渲染,避免打亂drawcall合批致份;
(4)將相關(guān)UI的Pos Z盡量統(tǒng)一設(shè)置為0变抽,Z值不為0的UI元素只能與Hierarchy中相鄰元素嘗試合批,所以容易打斷合批氮块。
(5)對(duì)于Alpha為0的Image绍载,需要勾選其CanvasRender組件上的Cull Transparent Mesh選項(xiàng),否則依然會(huì)產(chǎn)生DrawCall且容易打斷合批滔蝉。
最后選取合適的渲染管線與策略也是渲染性能與效果的關(guān)鍵击儡,比如使用URP做實(shí)時(shí)光照等。
物理模塊調(diào)優(yōu)
不使用物理引擎的項(xiàng)目蝠引,我們可以關(guān)閉物理引擎的Auto Simulation, 如果不用射線檢測(cè)等阳谍,還可以關(guān)閉物理的射線檢測(cè)(Auto Sync Transform)。物理引擎的迭代螃概,主要是在FixedUpdate去迭代物理世界的Update,如果FixedUpdate的調(diào)用頻率的次數(shù)越高矫夯,那么物理迭代次數(shù)就越高,更新越頻繁。物理引擎的迭代參數(shù)設(shè)置,如圖 1.1-1:
Fixed Timestep: 獨(dú)立于幀率吊洼,按照固定的時(shí)間間隔進(jìn)行迭代,物理引擎就是基于它训貌,迭代;
Maximum Allowed Timestep: 允許最大的時(shí)間步長, 物理計(jì)算的時(shí)間開銷,不允許超過這個(gè)值冒窍,限定了單幀的物理計(jì)算的最大時(shí)間, 所以這個(gè)值越小递沪,迭代的次數(shù)可能就越少。
可以通過調(diào)節(jié)這兩個(gè)值來調(diào)整物理引擎的迭代次數(shù)與開銷综液。由于FixedUpdate的迭代與幀率無關(guān)款慨,所以不要在FixedUpdate里面寫過多的復(fù)雜的邏輯。最后控制物理引擎中剛體的數(shù)目,這個(gè)結(jié)合自己的項(xiàng)目來做設(shè)定谬莹,用性能好的碰撞器來代替性能查的碰撞器檩奠。
動(dòng)畫模塊與粒子系統(tǒng)
控制Active Animator的一個(gè)方法是針對(duì)每個(gè)動(dòng)畫組件調(diào)整合理的Animator.CullingMode設(shè)置约素。該設(shè)置有三個(gè)選項(xiàng):
AlwaysAnimate:當(dāng)前物體不管是不是在視域體內(nèi),或者在視域體被LOD Culling掉了笆凌,Animator的所有東西都仍然更新圣猎;其中,UI動(dòng)畫一定要選AlwaysAnimate乞而,不然會(huì)出現(xiàn)異常表現(xiàn)送悔。
CullUpdateTransforms: 當(dāng)物體不在視域體內(nèi),或者被LOD Culling掉后爪模,邏輯繼續(xù)更新欠啤,就表示狀態(tài)機(jī)是更新的,動(dòng)畫資源中連線的條件等等也都是會(huì)更新和判斷的屋灌;但是Transform這些顯示層的更新就不做了洁段。在不影響效果的前提下把部分動(dòng)畫組件嘗試設(shè)置成CullUpdateTransforms可以節(jié)省物體不可見時(shí)動(dòng)畫模塊的顯示層耗時(shí)。
CullComplete:完全不更新共郭,適用于場景中相對(duì)不重要的動(dòng)畫效果祠丝,在低端機(jī)上需要保留顯示但可以考慮讓其靜止的物體,分級(jí)地選用該設(shè)置除嘹。
Animator還有個(gè)很重要的標(biāo)志就是開啟Apply Root Motion,如果動(dòng)畫不發(fā)生位移写半,就不要開啟這個(gè)選項(xiàng),開啟后可能會(huì)導(dǎo)致動(dòng)畫中Animator.ApplyBuiltinRootMotion開銷過高。
當(dāng)我們Active/Deactive一個(gè)Animator組件物體的時(shí)候尉咕,會(huì)導(dǎo)致Animator.Initialize函數(shù)的調(diào)用,當(dāng)檢測(cè)到這個(gè)開銷比較大時(shí)叠蝇,可以將其移出屏幕,比如關(guān)閉Animator組件,scale = 0,而代替activie/deactive。
粒子系統(tǒng)開銷與粒子系統(tǒng)數(shù)量和Playing狀態(tài)的粒子系統(tǒng)數(shù)量有關(guān)年缎。前者是指內(nèi)存中所有的ParticleSystem的總數(shù)量(包含正在播放的和處于緩存池中的)悔捶;后者指的是正在播放的ParticleSystem組件的數(shù)量(包含了屏幕內(nèi)和屏幕外),針對(duì)這兩個(gè)數(shù)值单芜,我們一方面關(guān)注粒子系統(tǒng)數(shù)量峰值是否偏高蜕该,可選中某一峰值幀查看到底是哪些粒子系統(tǒng)緩存著、是否都合理缓溅、是否有過度緩存的現(xiàn)象蛇损;另一方面關(guān)注Playing數(shù)量峰值是否偏高赁温,可選中某一峰值幀查看到底是哪些粒子系統(tǒng)在播放坛怪、是否都合理、是否能做些制作上的優(yōu)化股囊。在底端機(jī)上就可以考慮控制這些粒子數(shù)量袜匿,或者干脆關(guān)閉粒子特效來讓游戲流暢,具體可以從這個(gè)角度去操作與思考稚疹。
邏輯代碼調(diào)優(yōu)
邏輯代碼編寫就沒有什么可說的了居灯,平常注意一些開發(fā)代碼的習(xí)慣祭务,避免過的new 對(duì)象導(dǎo)致的GC等,提升算法的時(shí)間空間復(fù)雜度怪嫌,用空間換時(shí)間义锥,用時(shí)間換空間,多線程處理來發(fā)揮多核優(yōu)勢(shì), 做好代碼review岩灭。具體的結(jié)合自己的項(xiàng)目做好對(duì)應(yīng)的處理拌倍。
今天的分享就到這里了,關(guān)注我們學(xué)習(xí)更多的Unity開發(fā)的相關(guān)知識(shí)噪径。