![]()
【厚積薄發】精選了UWA社區的熱門話題,涵蓋了UWA問答、社區帖子等技術知識點,助力大家更全面地掌握和學習。本期 精選了2025年上半年的十大精彩問答分享給大家,期待UWA問答繼續有您的陪伴。
UWA 社區主頁:community.uwa4d.com
Q1:OpenGL中Shader LOD失效
我切換為OpenGL之后,發現切換Shader LOD的功能不能用了,切換為Vulkan沒問題,但是OpenGL就不行。同樣的Shader代碼,同樣的LOD配置。有什么解決思路嗎?
切換為OpenGL之后,Frame Debugger抓幀,都看不到那些本來要繪制的物體,感覺是完全沒有找到對應的LOD SubShader。
A1:Unity引擎里沒有處理好關于CBuffer變量的問題。如果CBuffer中有Shader用不到的變量,并且這個變量沒有在Properties中定義,那么就會導致對應的Pass直接不渲染。
修改方法就是,要么直接去掉這些不用的CBuffer中的變量,要么增加對應Properties中的定義。
感謝付炳楠@UWA問答社區提供了回答
A2:我也在Unity 2022.3.51f1c1里碰到類似的情況了,明明寫了3級LOD,結果永遠只有最大的那一級正常,中間或者更低的輸出的都是紅黑藍這種奇怪的顏色。
但是我Vulkan那邊同樣也是不正常的,不過在重新整理過CBuffer后痊愈了。
感謝王禹@UWA問答社區提供了回答,歡迎大家轉至社區交流:
https://answer.uwa4d.com/question/6784ada03d306f3e9d594e0f
Q2:iOS進程增加內存上限的接口
在打iOS包的時候注意到Xcode里有這么一個設置,在文檔里搜到了如下鏈接,說是能讓應用獲得更高的內存上限?實際效果怎么樣,有沒有什么副作用?大家有沒有用過?
https://developer.apple.com/documentation/bundleresources/entitlements/com.apple.developer.kernel.increased-memory-limit
A: 應該說的是Xcode里Increased Memory Limit這個設置。我們項目實測能讓iOS設備對APP因內存而閃退的臨界值從1.8GB上升到2.3GB,多出這500MB能做很多很多事了。
注意點基本也寫在文檔里了:只能在iOS15版本以上的設備使用;實際提升空間是跟硬件設備走的,要用接口os_proc_available_memory | Apple Developer Documentation(
https://developer.apple.com/documentation/os/3191911-os_proc_available_memory)查看;理論上,該設置搶占了其他進程的內存分配空間,所以有導致其他后臺進程被殺死的副作用風險。
該回答由UWA提供,歡迎大家轉至社區交流:
https://answer.uwa4d.com/question/67b2a8453d306f3e9d594e5f
Q3:關于CanvasRenderer.SyncTransform觸發調用的機制
已知UGUI主要耗時函數Rendering.UpdateBatches下的堆棧CanvasRenderer.SyncTransform調用次數較高確實會導致更高的整體耗時。看文檔和字面意思,應該是UI元素Transform信息變化后進行同步,但實際項目中測下來發現調用次數遠比預期的要高,所以這個東西實際的機制到底是什么?
A:在Unity 2021和2022的較新穩定版本上都做了實驗,發現有以下幾種情況:
1. 任何UI元素Transform信息變化(如位移、旋轉、拉伸,例如飄字這類Ul動畫)都會導致自身觸發一次CanvasRenderer.SyncTransform。若同時發生Transform信息變化的UI元素多,則顯然會導致調用次數高,比如像我們項目場景中玩家和野怪單位的大量HUD元素會隨著玩家視角變化頻繁位移。
2. 調用SetActive(True)激活UI元素時,會使當前Canvas下和其父Canvas下所有UI元素都觸發CanvasRenderer.SyncTransform。特別地,調用SetActive(False)隱藏UI元素時,不會觸發。
3. Instantiate實例化UI元素時,會使當前Canvas下和其父Canvas下所有UI元素都觸發CanvasRenderer.SyncTransform。
4. Destroy銷毀UI元素時,會僅使當前Canvas下所有UI元素都觸發CanvasRenderer.SyncTransform。
PS:以上API未實際生效時(如對一個已經被激活的對象調用SetActive(True)),則不會觸發CanvasRenderer.SyncTransform。
所以定位到問題后,優化手段上還是UI這塊老生常談的解放方案:即對1這種情況主要考慮控制更新頻率;對其他情況則是關注Canvas的層級設計,做好動靜分離。
該回答由UWA提供,歡迎大家轉至社區交流:
https://answer.uwa4d.com/question/67bbeb12682c7e5cd61bfa06
Q4:如何讓GameObject銷毀時無論是否Active過,都調用OnDestroy
請教一個問題,MonoBehaviour的OnDestroy方法,如果這個GameObject的實例化時就是隱藏的,銷毀時不會調用OnDestroy方法。我們項目有些核心邏輯是基于這個OnDestroy做的(時間太久遠,耦合太多邏輯不好改出去了)。有沒有什么辦法,可以讓這個GameObject銷毀時無論是否Active過,都調用OnDestroy。
A:要觸發OnDestroy,必須要觸發過Awake(Awake可以不明著寫出來),通常是被實例化或者第一次激活的時候觸發Awake,如果一直處于不激活的狀態,那么銷毀的時候不會自動觸發OnDestroy。所以可以在激活的父節點上主動SetActive一下:
![]()
感謝旋@UWA問答社區提供了回答
A2:1. 一般一個Prefab本身是點亮的,大部分是里面的某些節點才會隱藏。如果是我說的這種情況,應該是在根Prefab摧毀的時候主動調用一次需要控制調用的子組件。
![]()
2. 如果你真的是根Prefab就隱藏的那更簡單了:
(1)做一個工具掃描所有Prefab檢查并且修改點亮情況;
(2)編輯器模式下加載完一個Prefab之后檢查是否點亮,如果沒有則打印Error。
感謝沈杰@UWA問答社區提供了回答
A3:我們也遇到了這個,主要導致的問題自定義組件清理不掉Lua注冊過來的回調,導致返回登錄報錯。
我這邊解決思路是:在腳本反序列化之后,將自己注冊到UI根節點的管理腳本上,由這個管理腳本在Destroy時清理下面的子節點。
Base腳本如下圖:
![]()
有幾個要點說明下:
1. 我們只處理了UI(其他地方基本不會出這問題),項目的用法上每個UI根節點有必掛的組件,這個組件一定會執行Awake。
2. 如果組件自身Awake走到了,就不需要額外的銷毀管理,需要從管理器中將自己移除。
3. 反序列化接口中有一堆限制,要小心處理,比如常用的接口只能在主線程執行,如果在子線程要跳過。還有Prefab打開的編輯狀態也有一些狀態取不到,我這邊直接暴力忽略了(因為不常用)。
感謝Walker@UWA問答社區提供了回答,歡迎大家轉至社區交流:
https://answer.uwa4d.com/question/67d390183d306f3e9d594e7a
Q5:FairyGUI圖標文字合批失敗的原因
項目現在使用的是FairyGUI,界面中會有一排類似下圖的比較常見的組合按鈕(圖+特效+文字)。
![]()
在FrameDebugger中注意到這部分的DrawCall情況有點慘;老項目用UGUI+TMP作類似的UI應該是沒有問題都能合的。父節點FairyBatching是勾了的,圖集是合好了的,圖和圖、文字和文字之間應該也沒有互相遮擋覆蓋;考慮到可能是特效穿插的問題,所以運行調試時直接把特效的節點刪掉了,還是不行。請問還有什么思路?
![]()
A:遇到過類似的問題。首先FairyGUI的結構在導出后應該就是固定的了,有可能你運行時做了修改刪掉改掉某些東西,但原來的區域規格和UI元素仍然占位。所以這里刪特效、對TextField覆蓋面積的調試檢查,可能都得請UI同學幫忙,回到FairyGUI編輯器階段處理和檢查,再重新導出看效果。
操作了下,確實有變化。但現在又有兩個新問題:
1. 確實導出前就把特效移除有效果,但圖和文字中夾著特效是表現需要,最終不大可能刪,這個是不是就沒什么辦法了?
2. 就算移除了特效,還是發現只有圖和圖之間合了,文字之間仍然不合。而且這次是確認了TextField之間也沒有重疊。這時候看FrameDebugger合批失敗原因變成了超過300個頂點不能動態合批。請問這個怎么解決呢?
A: 第一個確實想不到什么辦法了。第二個就像FrameDebugger寫的一樣,你若是用了Shadow、Outline這種效果,文字的頂點就會成倍上升,再加上你字一多,就會超了。不過如果你這些表現上都要用的話,也和特效一樣沒什么辦法了。
感謝Faust@UWA問答社區提供了回答
A2: 這個看上去很像是文字和背景圖的區域相交導致的。之前有遇到過類似的問題,FairyGUI排序節點渲染順序用于動態合批的邏輯里,完全不相交、完全包含,這種情況沒問題,但是如果關系是相交的話,可能會阻止節點的排序。
感謝SunHowe@UWA問答社區提供了回答,歡迎大家轉至社區交流:
https://answer.uwa4d.com/question/67fcc756682c7e5cd61bfa57
Q6:粒子系統開啟Noise模塊在移動端的消耗如何
粒子系統開啟Noise模塊后在移動端的消耗如何,有什么使用建議嗎?
A:我在OPPO R17測了下,場景里播100個粒子系統*50粒子,前后分別設置為關閉Noise模塊、開啟Low/Medium/High Quality的Noise模塊,得到的粒子系統耗時變化如圖:
![]()
開啟Noise模塊后會使粒子系統耗時升高,主要開銷來自ParticleSystem.NoiseJob:
![]()
這么來看在移動端上的開銷還是比較可觀的,需要酌情使用。
使用時需要注意:
1. Octaves盡量低;
2. Quality盡量設置為Low;
3. 對粒子系統拆分,例如只對小部分設置較重的Noise,大部分使用較輕的Noise或者不開啟,等等。
感謝Faust@UWA問答社區提供了回答,歡迎大家轉至社區交流:
https://answer.uwa4d.com/question/6805b4613d306f3e9d594ec8
Q7:如何用GPU Instancing來優化樹木草石重復模型
項目場景里的樹木草石重復模型非常多,在嘗試用GPU Instancing來優化。使用的Shader應該是SRP Batcher和GPU Instancing都支持的,但是材質勾上GPU Instancing后看FrameDebugger里還是走的SRP Batcher,要怎么修改比較好呢?
A:如果 Shader兩個都兼容,就會優先走SRP Batcher的。常規做法就是把規劃要用GPU Instancing的物體用別的不走SRP Batcher的Shader;也可以考慮仍然用兩個都兼容的Shader,但是用MaterialPropertyBlock打斷SRP Batcher,這樣就會順延走GPU Instancing了。
感謝Faust@UWA問答社區提供了回答,歡迎大家轉至社區交流:
https://answer.uwa4d.com/question/680dd4d53d306f3e9d594ecc
Q8:URP相機如何將場景渲染定幀模糊繪制
URP有沒有什么方法能控制攝像機的渲染?比如現在有個功能是,載入副本后,馬上BOSS和場景的渲染定幀,然后模糊處理。在這期間基本是只渲染這個“UI效果”。場景暫時不渲染以實現優化。 如果完全實時的話,那么每幀都要渲染這種覆蓋全屏的大面片特效,和高斯模糊計算背景。
A: 可以寫一個CopyColor的Pass,將3D場景的內容渲染完后,用這個拷貝的Pass將內容保存下來,只拷貝一幀,然后將這個Pass Disable掉,再將3D渲染相機的CullingMask改為Nothing, 這個CopyColor的Pass里面的RT的內容可以用來做UI模糊處理。
感謝Faust@UWA問答社區提供了回答,歡迎大家轉至社區交流:
https://answer.uwa4d.com/question/68219ad6682c7e5cd61bfa65
Q9:為什么場景中沒有剛體更無碰撞事件但仍有較高物理耗時
為什么GOT性能報告和Profiler里看物理模塊耗時都很高?但其實這時候場景里已經沒有剛體了,按理說不會發生碰撞,只有在代碼里用了Raycast判斷子彈命中,后來我把設置里的物理模擬關掉,又打了包,物理耗時確實降了下來,看子彈還是能正常命中(因為是代碼調的),看粒子里的碰撞也還是能生效。
我不明白的是:之前那么高的物理耗時是在做什么?可能是什么導致的?是有一些我沒留意到的地方用了物理導致的,還是說Unity機制如此?(Unity版本2022.3.59)
A:的確, 當前Unity版本的機制就是這樣,很多時候必須要關閉掉物理模擬(指把Simulation Mode改成Script)才可以節省耗時。具體機制是場景中只要Static Collider數量大于0且沒有關閉物理模擬就會有耗時,和場景中有沒有剛體、有沒有發生碰撞事件無直接關聯。
針對以上問題,有經驗的朋友歡迎轉至社區交流:
https://answer.uwa4d.com/question/684688ea682c7e5cd61bfaa0
Q10:為什么使用發射Mesh的粒子系統會使Graphics內存暴漲
之前在UWA的分享里看到使用發射Mesh的粒子系統就會導致Memory Profiler-Graphics- 內存類型暴漲問題。我們項目美術同學也想用這種粒子,所以得評估一下這個問題(Unity 2022.3.27)。
A:自問自答一下,實際測下來好多開關和方法都沒什么用,限制這部分內存的只有發射Mesh的粒子系統組件數量、發射粒子的數量(通過Max Particle限制)和發射的Mesh的面數。
這么一看要么把這些因素控制到很低、要么還是索性不要用了,因為上漲的內存比Particle數量乘以每個Mesh的內存還要大一些,太容易一下就占好幾十MB了。
另外要卸載這些內存還沒法通過定向接口來做,非得調用RUUA。總之目前是不大敢用了,看后續有沒有修掉這個bug的Unity版本了。
針對以上問題,有經驗的朋友歡迎轉至社區交流:
https://answer.uwa4d.com/question/6858e8713d306f3e9d594eff
封面圖來源于網絡
今天的分享就到這里。生有涯而知無涯,在漫漫的開發周期中,我們遇到的問題只是冰山一角,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.