最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

手機游戲性能優(yōu)化1.1 移動端針對CPU端的性能調(diào)優(yōu)

2022-09-07 14:48 作者:博毅創(chuàng)為  | 我要投稿

前言

做手機游戲開發(fā)的時,經(jīng)常會遇到手機游戲的性能問題,手機游戲的性能問題可能有很多的方面,今天我們從CPU調(diào)優(yōu)的角度來給大家介紹一下常用的CPU調(diào)優(yōu)的一些經(jīng)驗和手段。這些經(jīng)驗和手段都有可能隨著時間與環(huán)境的變化改變而改變,具體還是要以實際的為準(zhǔn),先定位性能問題,再上具體的手段。接下來我們從CPU的性能調(diào)優(yōu)的角度來總結(jié)一下Unity手游開發(fā)中需要注意和優(yōu)化CPU的一些點。我們把手機游戲的CPU調(diào)優(yōu)分成幾個模塊,列舉一下每個模塊的一些經(jīng)驗,供大家參考。模塊如下:

(1) 渲染模塊;

(2) 物理模塊;

(3) 動畫模塊與粒子系統(tǒng);

(4) 邏輯代碼優(yōu)化;?

渲染模塊調(diào)優(yōu)?

渲染模塊是游戲開發(fā)中的性能大戶,首先建議開啟多線程渲染模式,在Unity項目中Project Setting里面默認(rèn)開啟了Multithreaded Rendering的,建議大家一般不要去改。單線程渲染流程中,游戲每一幀執(zhí)行的時候,先調(diào)用組件的Update, 做完大量的邏輯運算等,最后做渲染相關(guān)的指令調(diào)用。如果是單線程,就需要在主線程main thread里面去提交操作顯卡,在過程中容易產(chǎn)生主線程等待外部設(shè)備的狀態(tài)就緒等,照成卡頓導(dǎo)致幀率下降。而此時可能有其它的CPU核心處于空閑狀態(tài),所以為了發(fā)揮手機上的多核優(yōu)勢,我們可以把這部分用多線程來做,也就是是我們stats里面的render thread, 讓其它的CPU核心去處理這個事情,而不是讓主線程等在上面。對于開啟了多線程的渲染的游戲來說,還會有Gfx.WaitForPresent,等待渲染完成,如果這個函數(shù)非常耗時,說明了,目前GPU的工作壓力很大,這個時候就要考慮去優(yōu)化GPU相關(guān)的內(nèi)容。

影響渲染CPU執(zhí)行效率的本質(zhì)就是兩個東西,一個是渲染的面數(shù)(Triangle), 一個是渲染提交的次數(shù)(Drawcall)。這個部分很多開發(fā)者就會陷入一個所謂的標(biāo)準(zhǔn)”手機上模型一般多少個面合適?”這種問題其實沒有任何意義的,需要結(jié)合自己的游戲來進(jìn)行實測。時空背景不一樣,游戲玩法不一樣結(jié)果就不一樣。一半我們的做法就是到自己目標(biāo)客戶的機型上進(jìn)行實測。在我們的Shader確定后的效果下,我們目標(biāo)客戶的機型上面能跑多少個面。然后我們結(jié)合游戲的玩法,這些面放在哪些地方。比如近距離我們的面就分配得多,遠(yuǎn)距離就分配得少。重要主角面分配得多,不重要物體的面分配得少。也可以通過LOD工具在低端手機上減少模型面數(shù)。Drawcall大家比較熟悉了,有動態(tài)合批,靜態(tài)合批,SRP Batcher合批,GPU Instancing合批,具體可以參考教程《Unity 如何優(yōu)化Drawcall》。還有一個被很多人忽視的就是Set Pass Call開銷,在這個過程中,第一次加載Shader容易造成瞬間卡頓。Shader.CreateGPUProgram, 解決的方案是運行的時候做好Shader緩存,避免瞬間CPU卡頓。

渲染中還有一個比較讓人容易忽視的問題就是culling, 當(dāng)一個游戲場景中相機數(shù)目越多的時候culling的占比就可能會越高。另外如果場景中有很多的小物體,也可能會導(dǎo)致culling的耗時比較高,可以考慮動態(tài)加載分塊顯示,考慮使用Culling Group、Culling Distance來進(jìn)行優(yōu)化。另外還要注意一下開啟了遮擋剔除Occlusion Culling帶來的開銷。我們開啟遮擋剔除Occlusion Culling,確實降低了渲染的壓力,但是同時也增加了CPU的計算,如果發(fā)現(xiàn)Occlusion Culling,是性能瓶頸的時候,最后需要進(jìn)行開啟與關(guān)閉來權(quán)衡利弊。同時Culling中有FinalizeUpdateRendererBoundingVolumes函數(shù)占用過高,說明現(xiàn)在在游戲運行過程中不斷的更新物體的包圍盒,這個時候,可能需要檢查一下,哪些Skinned Mesh或者粒子導(dǎo)致了不斷的更新包圍盒,看能否避免。

在UGUI的優(yōu)化中,主要是檢查UI的邏輯響應(yīng)函數(shù)是否占用過高,同時把不用事件響應(yīng)的UI元素去掉選項”Raycast Target”, 這樣不用在每個UI元素去檢測用戶是否有UI操作,減少EventSystem.Update()耗時開銷。每個Canvas會調(diào)用BuildBatch為UI元素合并的Mesh。一旦UI元素發(fā)起移動,這樣就會引發(fā)BuildBatch, 合并過程是在其它線程處理的,如果合并的消耗過大,就會導(dǎo)致主線程發(fā)起等待。這個是我們我們可以把靜態(tài)的物體分到一個Canvas,動態(tài)的物體分到一個Canvas,這樣,能降低合并的難度與合并的開銷。UGUI的使用過程中也注意一下幾個點:

(1)同一Canvas下的UI元素才能合批。不同Canvas即使Order in Layer相同也不合批;

(2)盡量使用圖集,讓UI Drawcall合并有可能;

(3)在同一Canvas下、且材質(zhì)和圖集一致的前提下,盡量把同一個圖集的節(jié)點放一起渲染,避免打亂drawcall合批;

(4)將相關(guān)UI的Pos Z盡量統(tǒng)一設(shè)置為0,Z值不為0的UI元素只能與Hierarchy中相鄰元素嘗試合批,所以容易打斷合批。

(5)對于Alpha為0的Image,需要勾選其CanvasRender組件上的Cull Transparent Mesh選項,否則依然會產(chǎn)生DrawCall且容易打斷合批。?

最后選取合適的渲染管線與策略也是渲染性能與效果的關(guān)鍵,比如使用URP做實時光照等。?

物理模塊調(diào)優(yōu)?

不使用物理引擎的項目,我們可以關(guān)閉物理引擎的Auto Simulation, 如果不用射線檢測等,還可以關(guān)閉物理的射線檢測(Auto Sync Transform)。物理引擎的迭代,主要是在FixedUpdate去迭代物理世界的Update,如果FixedUpdate的調(diào)用頻率的次數(shù)越高,那么物理迭代次數(shù)就越高,更新越頻繁。物理引擎的迭代參數(shù)設(shè)置,如圖 1.1-1:

?

圖1.1-1

Fixed Timestep: 獨立于幀率,按照固定的時間間隔進(jìn)行迭代,物理引擎就是基于它,迭代;

Maximum Allowed Timestep: 允許最大的時間步長, 物理計算的時間開銷,不允許超過這個值,限定了單幀的物理計算的最大時間, 所以這個值越小,迭代的次數(shù)可能就越少。

可以通過調(diào)節(jié)這兩個值來調(diào)整物理引擎的迭代次數(shù)與開銷。由于FixedUpdate的迭代與幀率無關(guān),所以不要在FixedUpdate里面寫過多的復(fù)雜的邏輯。最后控制物理引擎中剛體的數(shù)目,這個結(jié)合自己的項目來做設(shè)定,用性能好的碰撞器來代替性能查的碰撞器。?

動畫模塊與粒子系統(tǒng)

使用新版的Mechanic動畫系統(tǒng)Animator控制動畫代替?zhèn)鹘y(tǒng)的Legacy的Animation控制動畫。功能上的好處比如人形動畫就不說了,在性能上骨骼動畫且曲線較多的動畫,使用Animator的性能是要比Animation要好,因為Animator是支持多線程計算的, Animator還可以通過開啟Optimized GameObjects進(jìn)行優(yōu)化。所以動畫控制Animator比Animation要高效一些。還有一種就是動畫在每個頂點在每一幀都Bake出來,用空間換時間的方法來做好處理,適合MOBA、SLG中的小兵具體可以參考《千人戰(zhàn)斗場景優(yōu)化》教程。

控制Active Animator的一個方法是針對每個動畫組件調(diào)整合理的Animator.CullingMode設(shè)置。該設(shè)置有三個選項:?

AlwaysAnimate:當(dāng)前物體不管是不是在視域體內(nèi),或者在視域體被LOD Culling掉了,Animator的所有東西都仍然更新;其中,UI動畫一定要選AlwaysAnimate,不然會出現(xiàn)異常表現(xiàn)。?

CullUpdateTransforms: 當(dāng)物體不在視域體內(nèi),或者被LOD Culling掉后,邏輯繼續(xù)更新,就表示狀態(tài)機是更新的,動畫資源中連線的條件等等也都是會更新和判斷的;但是Transform這些顯示層的更新就不做了。在不影響效果的前提下把部分動畫組件嘗試設(shè)置成CullUpdateTransforms可以節(jié)省物體不可見時動畫模塊的顯示層耗時。?

CullComplete:完全不更新,適用于場景中相對不重要的動畫效果,在低端機上需要保留顯示但可以考慮讓其靜止的物體,分級地選用該設(shè)置。?

Animator還有個很重要的標(biāo)志就是開啟Apply Root Motion,如果動畫不發(fā)生位移,就不要開啟這個選項,開啟后可能會導(dǎo)致動畫中Animator.ApplyBuiltinRootMotion開銷過高。?

當(dāng)我們Active/Deactive一個Animator組件物體的時候,會導(dǎo)致Animator.Initialize函數(shù)的調(diào)用,當(dāng)檢測到這個開銷比較大時,可以將其移出屏幕,比如關(guān)閉Animator組件,scale = 0,而代替activie/deactive。

Meshskinning.Update和Animators.WriteJob網(wǎng)格資源對于動畫模塊耗時的影響是十分顯著的。一方面,Meshskinning.Update耗時較高時。主要因素為蒙皮網(wǎng)格的骨骼數(shù)和面片數(shù)偏高,所以可以針對網(wǎng)格資源進(jìn)行減面和LOD分級。另一方面,默認(rèn)設(shè)置下,我們經(jīng)常發(fā)現(xiàn)很多項目中角色的骨骼節(jié)點的Transform一直都是在場景中存在的,這樣在Native層計算完它們的Transform后,會回傳給C#層,從而產(chǎn)生一定的耗時。在場景中角色數(shù)量較多,骨骼節(jié)點的回傳會產(chǎn)生一定的開銷,體現(xiàn)在動畫模塊的主函數(shù)之一PreLateUpdate.DirectorUpdateAnimationEnd的Animators.WriteJob子函數(shù)上。可以考慮勾選FBX資源中Rig頁簽下的Optimize Game Objects設(shè)置項,將骨骼節(jié)點“隱藏”,從而減少這部分的耗時。

粒子系統(tǒng)開銷與粒子系統(tǒng)數(shù)量和Playing狀態(tài)的粒子系統(tǒng)數(shù)量有關(guān)。前者是指內(nèi)存中所有的ParticleSystem的總數(shù)量(包含正在播放的和處于緩存池中的);后者指的是正在播放的ParticleSystem組件的數(shù)量(包含了屏幕內(nèi)和屏幕外),針對這兩個數(shù)值,我們一方面關(guān)注粒子系統(tǒng)數(shù)量峰值是否偏高,可選中某一峰值幀查看到底是哪些粒子系統(tǒng)緩存著、是否都合理、是否有過度緩存的現(xiàn)象;另一方面關(guān)注Playing數(shù)量峰值是否偏高,可選中某一峰值幀查看到底是哪些粒子系統(tǒng)在播放、是否都合理、是否能做些制作上的優(yōu)化。在底端機上就可以考慮控制這些粒子數(shù)量,或者干脆關(guān)閉粒子特效來讓游戲流暢,具體可以從這個角度去操作與思考。?

邏輯代碼調(diào)優(yōu)?

邏輯代碼編寫就沒有什么可說的了,平常注意一些開發(fā)代碼的習(xí)慣,避免過的new 對象導(dǎo)致的GC等,提升算法的時間空間復(fù)雜度,用空間換時間,用時間換空間,多線程處理來發(fā)揮多核優(yōu)勢, 做好代碼review。具體的結(jié)合自己的項目做好對應(yīng)的處理。?

今天的分享就到這里了,關(guān)注我們學(xué)習(xí)更多的Unity開發(fā)的相關(guān)知識。

Unity / 性能調(diào)優(yōu)篇

游戲程序員優(yōu)化指南

https://www.bycwedu.com/promotion_channels/695765628?

手機游戲性能優(yōu)化1.1 移動端針對CPU端的性能調(diào)優(yōu)的評論 (共 條)

分享到微博請遵守國家法律
阿鲁科尔沁旗| 博野县| 伊宁县| 岳阳市| 曲麻莱县| 天峻县| 泸西县| 武安市| 龙门县| 屏山县| 顺义区| 尼木县| 革吉县| 双柏县| 南充市| 新民市| 游戏| 汉中市| 大渡口区| 靖安县| 固安县| 宜良县| 墨竹工卡县| 阳高县| 曲水县| 安溪县| 邳州市| 阿鲁科尔沁旗| 崇信县| 阜南县| 香河县| 修文县| 石首市| 葫芦岛市| 邵阳县| 台南县| 大姚县| 平乡县| 芜湖县| 兴仁县| 拉孜县|