UWA每周推送的知識型欄目《厚積薄發 | 技術分享》已經伴隨大家走過了419個工作周。 精選了2024年十大精彩問答分享給大家,期待2025年UWA問答繼續有您的陪伴。
UWA 社區主頁:community.uwa4d.com
Q1:PuerTS和HybridCLR哪個更適合開發微信小游戲
PuerTS和HybridCLR哪個更適合開發微信小游戲?哪個更快?大家有做過相關的調研嗎?
A1:之前測過,HybridCLR的解釋器是在WASM上的,而JS用的是微信的。這倆算力估計差了50多倍。但現在市面好像沒有好的Unity和TS的框架。
JS算力高,但和WASM交互比HybridCLR低幾倍。
感謝子非魚@UWA問答社區提供了回答
A2:可以參考以下文章,但綜合來看應該還是HybridCLR更好一些:
https://zhuanlan.zhihu.com/p/646932579
感謝旋@UWA問答社區提供了回答,歡迎大家轉至社區交流:
https://answer.uwa4d.com/question/66a70d55682c7e5cd61bf888
Q2:如何解決穿插易導致半透明物體合批失敗
請問半透明Shader,距離穿插,打斷SRPBatcher。有什么通用解法?比如一個火焰特效,用了ab2個粒子,分別2個Shader,那么10個火焰就是ab ab ab......這樣20個DrawCall嗎?但完全無法合批。
由于半透明開銷比較大。而且需要渲染順序嚴格導致了一些優化失效。大家有什么好的解法嗎?
A1:不透明可以調RenderQueue,半透明不好調,可能會影響渲染結果。
感謝AQ(Richard Pan)@UWA問答社區提供了回答
那比如玩家丟出的燃燒瓶,多少米合并成一個?如果很遠,半透明物體在火堆之間就出錯明顯。我之前是3米合成一次順序,提升不明顯。
A2:我是直接不同材質用不同隊列,犧牲了一些順序正確性,主要用在團戰時候大量技能特效上,本身畫面很亂,順序錯誤感受不出來,至于場景中的常駐特效,還是要保證順序正確性,不去調隊列。
對應性能好的機器保證正確性,性能差點的保證性能,忽略點正確性。
感謝AQ(Richard Pan)@UWA問答社區提供了回答
A3:一個燃燒瓶丟出來8份火焰實例,每個實例3個粒子發射器且Shader不同,導致一堆開銷。嘗試燃燒瓶互相順序不嚴謹,內部定死順序看看。
感謝偶爾不帥@UWA問答社區提供了回答
強制改變渲染順序粒子是改下圖這里好:
還是材質的Queue好:
A4:我是改材質的Queue。
感謝AQ(Richard Pan)@UWA問答社區提供了回答
A5:半透明大部分情況是放棄跨發射器的合批優化。整理了以下幾種辦法供參考,一種辦法就是將兩個材質合并為一個,這樣就連上了;另外就是在Batch的時候判斷屏幕Bounds,不重疊的時候進行批次合并;還有種辦法是粒子實時Batch成序列幀后使用,遠處的粒子可以這樣處理,這樣這些粒子都可以一個批次畫完,畢竟遠處不管是大小還是幀率都很低,這樣做反而可能是合算的。
感謝flashyiyi@UWA問答社區提供了回答,歡迎大家轉至社區交流:
https://answer.uwa4d.com/question/675673e5682c7e5cd61bf9bf
Q3:Unity引擎關于APP后臺下載支持的實現問題
最近很多游戲在Loading界面會標明支持后臺下載模式,項目也計劃實現一個,首先找到了Unity自帶的BackgroundDownload解決方案,功能是可以的,也好接入,但項目中的文件數量比較多,有大幾萬個,同時建立這么多鏈接非常卡頓,經過簡易優化,速度提升了一些,同時平滑建立連接數不再那么卡頓,但所有連接建立完還是需要很長時間,同時Android環境在創建1000+個下載服務時,會崩潰,沒有明確的報錯,每次會有下圖中的異常!
BackgroundDownload
https://github.com/Unity-Technologies/BackgroundDownload
咨詢下各位大佬,如下幾個問題:
1. 崩潰如何處理?
2. 如何平滑快速地建立起下載連接?
3. 有沒有其他更好的處理類似問題的解決方案?
A1:可以試試以下方案:
方案1:把所有要下載的任務,放到1個隊列,開多個線程去處理這個隊列的下載任務,并且限制設定同時下載的任務數。
方案2:把對應資源,根據一些規則(如:等級1-10級會用到的資源在1個zip包,11-20級會用到的資源放在1個zip包),然后根據一些條件在不同時刻來下載不同的zip包。
感謝hejianchun@UWA問答社區提供了回答
A2:目前匯總下Android端的解決方案,幫助大家踩坑:
1. Unity內部使用后臺運行的線程來平滑控制下載量,存在的問題:APP切入后臺時,線程會被掛起,中斷傳輸;
2. 將下載任務全部篩入原生層,使用Android的Service調起,同線程也是會被掛起;
3. 將下載任務全部篩入原生層,使用Android的Schedule等定期任務,存在的問題:觸發時間不固定,時間選擇范圍大,但系統會設置最小調用間隔為15分鐘,沒法用;
4. 將下載任務全部篩入原生層,使用Android的前臺Service中起一個線程,逐步傳遞給下載服務,存在的問題:目前可以持續運行,但會受到系統的限制,服務起的線程觸發時間會時快時慢,執行一段時間后有概率會掛起(沒有明顯的輸出,不明原因,就是長期不輸出日志了,服務都還在)。
用服務搞定后發現Android的原生下載服務速度很慢,所以再次測試了Unity中使用C#的Thread的方案(線程設置為inbackround=true,使用HttpClient下載),發現是可以后臺運行且速度可以,之前測試不清楚為什么不行,可能是哪里遺漏了。
另外補充幾點:
如果后臺不運行了,可以在手機的電池管理處,勾選允許你的APP在后臺運行選項;
Android是可以申請忽略電池優化權限的;
但Google對這個權限有很多限制。
感謝題主Will@UWA問答社區提供了回答
A3:由于國內Android系統的各種定制化,使用BackgroundDownload方案會在某些機型上無法下載,并且無法解決。
感謝kakacoding@UWA問答社區提供了回答
A4:開個線程驅動下載隊列,http下載,不要用UnityWebRequest。
感謝李晨曦@UWA問答社區提供了回答,歡迎大家轉至社區交流:
https://answer.uwa4d.com/question/65e1c0b13625c22cffcb1e3d
Q4:使用SBP打AssetBundle腳本引用丟失
最近項目實驗升級ScriptableBuildPipeline打包AssetBundle(之前使用的是BuildIn構建管線)。使用的Unity為2022.3,SBP版本為2.1.4。
結果發現打出的UI AssetBundle中,部分NGUI的腳本丟失引用了,丟的最多的是UIButton。但也不是所有UI都會丟失,有的就正常。BuildIn管線打包也正常。
真機上加載資源的時候會報錯:
Error: A scripted object (script unknown or not yet loaded) has a different serialization layout when loading. (Read 32 bytes but expected 8136 bytes)
Did you #ifdef UNITY_EDITOR a section of your serialized properties in any of your scripts?
UnityEngine.AssetBundle:LoadAsset(String)
使用AssetStudio解包AssetBundle,發現腳本的m_PathId為0。求助,這可能是哪的問題?
A1:針對出問題的文件單獨導出獨立工程Demo去調試。
發現出問題的情況是AssetBundle的引用的引用也包含了相同的腳步且這個引用也是打AssetBundle的, 應該是遞歸引用的時候出問題了。
解決方案:
1. 設置SBP中BuildParameters的NonRecursiveDependencies為false。
修改方法:
a. 將Library\PackageCache夾子下SBP的組件移動到Packages下變為本地組件,即可編輯代碼。
b. 使用SBP非兼容模式接口構建,New出BuildParameters,然后可修改此屬性。
2. 將腳本信息都寫入到一個獨立的Bundle中,這樣所有Bundle都引用它即可,這種方式需要啟用CreateMonoScriptBundle。
修改方法:
在SBP組件中的DefaultBuildTasks腳本Create接口內Return出AssetBundleCompatible(false, true);即可。
感謝題主mr.Tian@UWA問答社區提供了回答
A2:感謝樓主的回答,我們項目用的Addressable,當A預設(A單獨打包)引用公共預設B的時候,會出現部分腳本和Image組件丟失的情況,查看AssetBundle的信息發現丟失了腳本的相關信息,采用樓主的建議,把NonRecursiveDependencies設為false就解決了。
感謝Jeff@UWA問答社區提供了回答,歡迎大家轉至社區交流:
https://answer.uwa4d.com/question/66babdd6682c7e5cd61bf8ae
Q5:升級Unity后產生的Objects內存泄露現象
項目升到2022.3.28后觀察到在真機上出現了之前沒有的內存泄漏狀況,用Memory Profiler排查后發現除了一些正常的資源和堆內存有輕微上升外,主要是有一部分Native-UnitySubsystemsObjects- 泄露很明顯,但沒法定位。請問有沒有人遇到這個問題?怎么解決?
A1:可以參考下這篇官方論壇討論和復現測試鏈接:
https://discussions.unity.com/t/memory-leak-in-scriptableobject-containingserializereference-in-android-environment/946666
https://issuetracker.unity3d.com/issues/memory-leak-when-using-serializereference-in-il2cpp-build
根據我們項目中的情況加上自己試驗了下,發現觸發條件比帖子中還要簡單,都不用ScriptableObject+Addressable,只要任意帶有[SerializableReference]特性的資源被銷毀就會發生泄漏。而且看樣子這個問題大概率會出現在所有2022以上及團結引擎的項目中,且目前未被修復。
考慮到使用這些Unity版本一般是基于支持鴻蒙或支持小游戲的主要目的,不大可能回退版本,那么目前處理方法可能就是要盡量避免使用這個特性。甚至像DoTween這種可能涉及該特性的插件建議都要換掉。
該問答由UWA提供
A2:Unity已經修復了該問題。遇到該問題的可以通過升級引擎到最新版本解決。
感謝Faust@UWA問答社區提供了回答
A3:Unity 2022.3.34版本修復,團結1.3.1版本修復。
感謝K@UWA問答社區提供了回答,歡迎大家轉至社區交流:
https://answer.uwa4d.com/question/670c8262682c7e5cd61bf95c
Q6:Unity中如何實現草的LOD
Unity自帶的Terrain中草作為Detail,無法設置LOD Group。感覺草的LOD應該是一個非常基礎的功能,Unity選擇不支持這個功能的原因是什么?要想實現草的LOD,我想到的幾種方式,還有更好的實現方式么?
1. 手動放置。
2. 自己寫Procedural工具批量生成。
3. 使用Terrain的Paint Trees功能變通實現。即把草當作一種Tree,增大種植密度。不知道這種實現會不會有副作用。
A1:LOD一般不用于草,通常大批量的草都是使用GPU Instance。如果距離遠的草,你可以通過邏輯控制遠距離草的顯示和隱藏。
感謝qingfeng@UWA問答社區提供了回答
A2:草通常是小型和密集的,對于這些對象應用LOD機制可能并不會顯著提高性能。草地的渲染通常依賴于地形的著色器和草地批處理,因此Unity可能認為不需要為這些小對象單獨設置LOD。
如果要快速解決問題,可以看看Unity Store中的Infini GRASS GPU Vegetation。
感謝蕭小俊@UWA問答社區提供了回答,歡迎大家轉至社區交流:
https://answer.uwa4d.com/question/65fe527f5c7f5d2c5805d354
Q7:開發微信小程序游戲,有沒有類似
Debug真機圖形的方法
開發微信小程序游戲有什么科學的Debug真機圖形的方法嗎?比如RenderDoc?
A1:推薦Frame Debugger,團結可用。
感謝tmp@UWA問答社區提供了回答
A2:1. 游戲可以在瀏覽器跑的話,可以用SpectorJS( https://github.com/BabylonJS/Spector.js/ )。
2. RenderDoc曾經也可以抓Chrome,但后來官方禁了,可能需要自己魔改編譯一個RenderDoc。
3. 也可以用MuMu模擬器+RenderDoc抓微信,MuMu需要開啟Vulkan模式,RenderDoc開全局Hook,Attach到MuMu的進程上,但是抓到的是Vulkan的API。
感謝littlesome@UWA問答社區提供了回答
A3:RenderDoc可以考慮,但需要舊版本的RenderDoc。或者配合模擬器截幀,或者Root的手機都可以,或者用瀏覽器都行,方式很多,個人推薦模擬器+截幀。
感謝司馬老師@UWA問答社區提供了回答,歡迎大家轉至社區交流:
https://answer.uwa4d.com/question/677250003d306f3e9d594de3
Q8:MemoryProfiler中Graphics/No Name
內存怎么排查
移動端項目,發現某個場景里內存上升很快、但切場景又能回落回去。在Memory Profiler里看發現是Graphics下面的 ,怎么排查?Unity版本是2022.3.37。
A:這個我們之前也遇到過,可以看下這個場景是不是用了發射Mesh的粒子?應該是臨時生成的網格都造成了內存占用,雖然沒有引用,但要在下次場景切換RUUA的時候才自動卸載。
該回答由UWA提供,歡迎大家轉至社區交流:
https://answer.uwa4d.com/question/673af015682c7e5cd61bf994
Q9:移動平臺紋理壓縮格式選擇ASTC,
美術出圖還需遵守POT嗎
移動平臺紋理壓縮格式選擇ASTC,美術出圖大小還有要求嗎?
1. 美術出圖還需要遵守POT(2的冪次方)嗎?
2. 如果使用NPOT(非2的冪次方),性能方面有多大影響?
A1:如果是作用于3D場景中物體的貼圖而需要開啟Mipmap的紋理,則仍需要滿足POT。否則,ASTC+Mipmap+NPOT,仍然會導致紋理在真機上被解析為RGBA32未壓縮格式;以ASTC4*4為例,變為RGBA32則內存占用變為四倍,且相應的包體大小、加載耗時、帶寬開銷等其他內存開銷也都會顯著上升。
如果不需要開啟Mipmap的呢,性能方面有影響嗎?
A2:3D場景物體貼圖(模型甚至特效和Spine等只要和相機有距離變化或者縱深的物體)理論上開啟Mipmap都有利于降低帶寬開銷;若確實不需要開啟Mipmap的紋理(如UI元素用到的紋理),關閉Mipmap后使用NPOT分辨率理論上對性能不會有什么影響。
感謝Faust@UWA問答社區提供了回答,歡迎大家轉至社區交流:
https://answer.uwa4d.com/question/672edc1f3d306f3e9d594d88
Q10:Application.lowMemory在什么時候會生效
Application.lowMemory這個方法大家有測過嗎?如何生效?
A1:由于Application.lowMemory僅在內存極其緊張時觸發,因此不應該過度依賴這個回調來管理內存,尤其可能比較常見但其實有問題的、在回調中調用RUUA回收Unused資源的做法,不但降低內存的效果有限還會觸發卡頓。正確的做法是通過優化資源管理、減少不必要的內存占用等方式來預防內存問題;或調用Resources.UnloadAssets或AB.Unload(True)的方式定向卸載內存。
該問答由UWA提供
A2:Application.lowMemory說明如圖:
iOS系統,比如普通4G設備,閃退內存也大概為2G左右,通過Xcode可以看到一個紅線,到了紅線即觸發閃退,在2G前的一定內存回收到lowMemory,下圖的藍色驟降的地方就是收到lowMemory釋放內存,可以作為內存釋放的保底方案,只要不是突然申請比較大的內存應該都可以(像最右端的就是突然一大塊內存達到了Limit直接閃退)。
Android的觸發時機就有點不確定了,這是官方文檔:
https://developer.android.com/reference/android/app/Application.html#onLowMemory%28%29
上圖說的是系統內存不足會觸發,通常是在所有后臺進程被殺死時候(但是也說了沒有明確的觸發時機,只是通常是所有后臺進程被殺死)。
但是測試下來發現,后臺APP被殺的時候是能收到lowMemory的,但是可能根據不同廠商,可能不是所有后臺APP都被殺之后才收到lowMemory。
感謝范世青@UWA問答社區提供了回答,歡迎大家轉至社區交流:
https://answer.uwa4d.com/question/66f8cd1a682c7e5cd61bf8e6
封面圖來源于網絡
今天的分享就到這里。生有涯而知無涯,在漫漫的開發周期中,我們遇到的問題只是冰山一角,UWA社區愿伴你同行,一起探索分享。歡迎更多的開發者加入UWA社區。
UWA官網:www.uwa4d.com
UWA社區:community.uwa4d.com
UWA學堂:edu.uwa4d.com
點擊下方名片關注我們,將我設為星標,及時接收小編每日推送哦,性能優化不迷路~
近期精彩回顧
特別聲明:以上內容(如有圖片或視頻亦包括在內)為自媒體平臺“網易號”用戶上傳并發布,本平臺僅提供信息存儲服務。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.