1)子線程GC導(dǎo)致主線程函數(shù)耗時(shí)較高的問題
2)升級(jí)Unity大版本后,Text顏色修改問題
3)清除增量式GC導(dǎo)致的Mono堆內(nèi)存泄漏問題
4)多Pass合批優(yōu)化問題
這是第274篇UWA技術(shù)知識(shí)分享的推送。今天我們繼續(xù)為大家精選了若干和開發(fā)、優(yōu)化相關(guān)的問題,建議閱讀時(shí)間10分鐘,認(rèn)真讀完必有收獲。
UWA 問答社區(qū):answer.uwa4d.com
UWA QQ群2:793972859(原群已滿員)
Rendering
Q:在主線程中有非常多的卡頓,從UWA的報(bào)告中看到很多異常的高耗時(shí),請(qǐng)問可能是什么原因造成的?

A:像上面這樣的頻繁卡頓,且卡頓函數(shù)種類非常多的情況,應(yīng)該是子線程分配了非常多的堆內(nèi)存,導(dǎo)致子線程GC,從而卡住了主線程。當(dāng)GC的時(shí)候,主線程可能會(huì)處于各種階段,因此對(duì)應(yīng)階段的函數(shù)耗時(shí)就會(huì)包括等待GC的耗時(shí)??梢詮腢WA的Mono報(bào)告中查看是否有子線程分配了大量的堆內(nèi)存,通常是由這種(Thread)打頭的子線程函數(shù)的分配導(dǎo)致的。

感謝han@UWA問答社區(qū)提供了回答,歡迎大家轉(zhuǎn)至社區(qū)交流:
https://answer.uwa4d.com/question/6180e0f28f8c834241fd6930
UGUI
Q:從Unity 4.6.9f1升級(jí)到Unity 2020.3.2.f1c1。首次Unity升級(jí)之后UI的Text顏色修改是正常。當(dāng)運(yùn)行一次之后,所有的Text顏色都無法修改了。就算新創(chuàng)建一個(gè)新的Text也無法修改。
A:會(huì)有多余的UI-Default和UI-DefaultFont這兩個(gè)Shader,刪除它們,然后重啟Unity就好了。
感謝芝麻青豆角@UWA問答社區(qū)提供了回答,歡迎大家轉(zhuǎn)至社區(qū)交流:
https://answer.uwa4d.com/question/6185085fd8413e18eb034520
Mono
Q:最近在研究Mono堆內(nèi)存時(shí),發(fā)現(xiàn)一幀內(nèi)分配多次較大內(nèi)存,會(huì)導(dǎo)致內(nèi)存無法被回收。
過程如下:
在同一幀內(nèi)調(diào)用三次分配100MB內(nèi)存的方法,分配內(nèi)存的變量都是在各自的作用域,在這之后調(diào)用GC.Collect()。發(fā)現(xiàn)有較大幾率出現(xiàn)100MB或者200MB無法被回收的Mono堆內(nèi)存。經(jīng)過排查之后發(fā)現(xiàn)取消勾選Incremental GC之后,內(nèi)存就能完全被收回。
我推測(cè)是每次申請(qǐng)內(nèi)存的時(shí)候會(huì)執(zhí)行一次GC,清除上一次分配的內(nèi)存,但是由于使用增量GC,無法在本幀完成回收工作。再下一次GC的時(shí)候,第二次GC的回收內(nèi)容被重置了,導(dǎo)致第二次的GC需要被回收的內(nèi)存就泄漏了。
不知道我這么理解是不是對(duì)的,希望大佬們解惑。同時(shí)希望大佬告知有沒有辦法清除這部分內(nèi)存。
測(cè)試環(huán)境:
Unity 2019.4.15c1
Unity 2020.4.15f2
測(cè)試平臺(tái):
安卓 Mono
以下為測(cè)試代碼:



A:通過題主的方法,我也復(fù)現(xiàn)了該問題。我還是比較贊同你的理解的。
Unity官網(wǎng)的一篇關(guān)于增量GC的博客也寫了該方法的弊端:

它的正常運(yùn)行是需要前提的,那就是在GC期間這些被標(biāo)記為“需要清理的內(nèi)存”都保持不變。如果在GC期間變化了,比如頻繁分配大量?jī)?nèi)存,那么就需要重新標(biāo)記一遍,而這個(gè)階段可能會(huì)有意想不到的bug產(chǎn)生。內(nèi)存泄漏很可能就是發(fā)生在這個(gè)階段(我也只是猜測(cè))。
不過個(gè)人覺得增量GC仍然是一個(gè)良好的嘗試,雖然它只是測(cè)試階段,也存在著一些問題,但是以前的Boehm-Demers-Weiser garbage collector很容易引起高耗時(shí)峰值從而造成卡頓,而分代式GC正是為了減輕峰值的影響,盡量確保流暢性。
可以參考官方博客:https://blog.unity.com/technology/feature-preview-incremental-garbage-collection
該回答由UWA提供,歡迎大家轉(zhuǎn)至社區(qū)交流:
https://answer.uwa4d.com/question/61658ad48f8c834241d92a0b
Rendering
Q:游戲使用簡(jiǎn)單的Mesh顯示幾十張撲克牌,為了效果,材質(zhì)Shader使用了2個(gè)Pass,其中一個(gè)是拉伸做邊緣效果,但是由于是多Pass,即使是相同的材質(zhì)和貼圖,還是不能動(dòng)態(tài)合批,請(qǐng)教這種情況有沒有什么優(yōu)化方案?
1. 不能合批,但是材質(zhì)是相同的,順序渲染過程中是否有什么狀態(tài)切換的消耗?
2. 能否使用兩個(gè)Mesh,不同的材質(zhì),Shader都使用單Pass,區(qū)別是一個(gè)Mesh是正常顯示,一個(gè)Mesh僅僅做拉伸邊緣效果,理論上是不是不超過頂點(diǎn)數(shù)的情況下可以兩次動(dòng)態(tài)合批?
A1:Unity BuiltIn渲染管線不支持多Pass合批,多Pass的Shader通過Set Pass call逐個(gè)渲染每個(gè)Pass后才會(huì)繼續(xù)渲染下一個(gè)Object重復(fù)一遍,所以會(huì)產(chǎn)生比較多的Draw Call。
更好的辦法就是用自定義的渲染管線的方式渲染多個(gè)Pass。在渲染第一個(gè)Pass的時(shí)候,把所有的Object一次性全都渲染了,渲染完畢之后通過一次Set Pass Call去渲染下個(gè)Pass,可以試下URP渲染管線。
感謝星傲蝶戀@UWA問答社區(qū)提供了回答
A2:題主說的第二點(diǎn)是比較常規(guī)的做法,要注意的是為了防止Draw Call的穿插,需要調(diào)整這兩種渲染的RenderQueue,將他們對(duì)應(yīng)的RenderQueue錯(cuò)開。
感謝Xuan@UWA問答社區(qū)提供了回答,歡迎大家轉(zhuǎn)至社區(qū)交流:
https://answer.uwa4d.com/question/6178c9c58f8c834241f2aaeb
20211108
更多精彩問題等你回答~
Unity增量打包AssetBundle沒變化的資源也會(huì)被重新打包
在模型有UV2的情況下開啟Generate Lightmap UVs
封面圖來源于網(wǎng)絡(luò)
今天的分享就到這里。當(dāng)然,生有涯而知無涯。在漫漫的開發(fā)周期中,您看到的這些問題也許都只是冰山一角,我們?cè)缫言赨WA問答網(wǎng)站上準(zhǔn)備了更多的技術(shù)話題等你一起來探索和分享。歡迎熱愛進(jìn)步的你加入,也許你的方法恰能解別人的燃眉之急;而他山之“石”,也能攻你之“玉”。
官網(wǎng):www.uwa4d.com
官方技術(shù)博客:blog.uwa4d.com
官方問答社區(qū):answer.uwa4d.com
UWA學(xué)堂:edu.uwa4d.com
官方技術(shù)QQ群:793972859(原群已滿員)