這是第222篇UWA技術知識分享的推送。今天我們繼續為大家精選了若干和開發、優化相關的問題,建議閱讀時間10分鐘,認真讀完必有收穫。
UWA 問答社區:answer.uwa4d.com
UWA QQ群2:793972859(原群已滿員)
本期目錄:
Q:Unity裡用FrameDebug顯示DrawCall是422個,Batches是435個,在SnapDragonProfiler裡抓取出來glDrawElements數目是1449個,怎麼理解這種差異?
A1:可參考以下幾點:
1. 題主的數據有一點問題,DrawCall數目應該大於等於Batches。根據特定的規則,多個DC可以視為一個Batch,一個Batch中包含多個DrawCall,節省了一部分CPU提交數據的操作。
2. 調用glDrawElements函數進行繪製就是DrawCall的一種形式。
感謝Vest@UWA問答社區提供了回答
A2:這部分可以參考UWA DAY 2020裡張強老師的分享《Unity移動遊戲項目優化案例分析(上)》(https://edu.uwa4d.com/course-intro/1/197)中的第二小節。
感謝範君UWA問答社區提供了回答,歡迎大家轉至社區交流:
https://answer.uwa4d.com/question/5f33b10e9424416784ef1bdd
Q1:渲染大面積草地時,如何降低消耗?
A1:有以下幾點:
1. 使用DrawMeshInstance。
2. 上面這個API是不會進行視距剔除,視錐體剔除和遮擋剔除的。
下面有兩種方案:
a. 將草地按區域分組,用每組的中心點計算視距,依據距離切換網格LOD或剔除。
還能用向量點乘簡單剔除在相機後方的草地。(注意臨界問題)
b. 藉助CullingGroup。
CullingGroup.onStateChanged事件綁定,通過事件觸發調整傳入DrawMeshInstanced的Matrix順序和渲染數量。(比較難的是,DrawMeshInstanced只能指定渲染前幾個Matrix)
通過cullingGroup.SetBoundingSpheres實現視錐體剔除和遮擋剔除;
通過cullingGroup.SetBoundingDistances實現視距剔除和LOD;
這個方案也最好進行區域分組,不然CullingGroup的事件監聽佔用會比較高。中端機上4000個監聽會佔約2ms。
以後如果有對比兩種方案的性能,我再進行補充。
附:
《CullingGroup API的使用說明》
https://blog.csdn.net/foxyfred/article/details/74357093
《Unity 3D研究院之Lightmap支持GPU Instancing》
https://www.xuanyusong.com/archives/4640
《如何高效使用GPU Instancing技術來進行草叢渲染》
https://edu.uwa4d.com/course-intro/0/78
《Unity2018升級DrawMeshInstanced不生效》
感謝題主李先生@UWA問答社區提供了回答
A2:可以使用Indirect模式的Instancing,配合ComputerShader實現視錐剔除和遮擋剔除。
感謝鄒春毅@UWA問答社區提供了回答
A3:推薦一個使用URP製作的草海效果,親測可在Mobile端使用。
Unity URP Mobile Draw Mesh Instanced Indirect Example:
https://lab.uwa4d.com/lab/5f1f503e0f247485d93d9016
性能測試:
can handle 10 million instances on Samsung Galaxy A70 (GPU = adreno612, not a strong GPU), 50~60fps, performance mainly affected by visible grass count on screen(draw distance = 125)
can handle 10 million instances on Lenovo S5 (GPU = adreno506, a weak GPU), 30fps, performance mainly affected by visible grass count on screen(draw distance = 75)
感謝Vest@UWA問答社區提供了回答,歡迎大家轉至社區交流:
https://answer.uwa4d.com/question/5e919a528cabe84a011afcde
Q:HUD為什麼會隨著攝像機偏移?
代碼如下:
Vector3 midVe1 = obj.transform.position;
Vector2 viewPose = worldCamera.WorldToViewportPoint(midVe1 + new Vector3(0, 2, 0));
viewPose.x *= Screen.width;
viewPose.y *= Screen.height;
hud.anchoredPosition = viewPose;
圖片如下:
A:題主說的這現象是合理的。
Vector2 viewPose = worldCamera.WorldToViewportPoint(midVe1);
Vector2 viewPose = worldCamera.WorldToViewportPoint(midVe1 + new Vector3(0, 2, 0));
這兩個算出來的viewPos.x是不一樣的。所以可以改成先算x,再偏移y。大概是這樣:
Vector3 midVe1 = obj.transform.position;
Vector2 viewPose = worldCamera.WorldToViewportPoint(midVe1);
viewPose.x *= Screen.width;
viewPose.y *= Screen.height;
viewPose.y += 130;
hud.anchoredPosition = viewPose;
這裡面y方向上的偏移值(130)就要自己調整了。
感謝Xuan@UWA問答社區提供了回答,歡迎大家轉至社區交流:
https://answer.uwa4d.com/question/5f804eff9424416784ef2587
Q1:針對Unity中如何在豎屏模式的UI之上顯示強制橫屏的UI,我們現在有兩種思路:
1. 改Screen.orientation之後再顯示。
2. 將新UI旋轉依z軸轉-90度顯示。
請問,兩者哪種更好呢?
A1:一個簡單的方式:
Canvas的RenderMode改成World Space,管它攝像機怎麼裁剪,UI畫布也不會發生變化。
如果自適應不了,在Canvas上根據你自己的需求做好自適應就好。
感謝鄭驍@UWA問答社區提供了回答
A2:我們之前項目裡剛好有個類似的需求,在橫屏遊戲中,個別玩法切換到豎屏。
當時採用的解決方案是修改Screen.orientation,同時修改UI全局根節點上的CanvasScaler的referenceResolution(豎屏時設置為1080,1920,橫屏設置為1920,1080),matchWidthOrHeight(和項目的適配策略相關,豎屏時設置為0,橫屏時為1),切換時會有一個全屏遮罩的fade效果,來避免切換時顯示錯誤。
感謝範君@UWA問答社區提供了回答
Q2:請問為什麼不考慮轉90度的做法?
A:我們當時沒有測過旋轉的方案。現在大概想想有兩個問題:
1. 單純旋轉角度應該只能在橫屏的中間部分顯示一個豎屏界面吧?感覺還需要其他處理。
2. 對工作流是否有影響,如果要一個豎屏界面是否是要在製作時先做成一個橫屏界面?內部控制項是否要處理?例如最終呈現出豎屏效果的劇情文字從左到右出現,旋轉之前應該是橫屏的從下到上出現,同時每個單一文字也是旋轉的。
感謝範君@UWA問答社區提供了回答
Q3:RectTransform的尺寸會被延遲修改這件事, 沒有造成什麼問題嗎?
A:印象中沒有遇到什麼大問題。不過我們當時這類需求切換時都是全屏UI,加了遮罩Fade後沒有什麼明顯的穿幫。
感謝範君@UWA問答社區提供了回答,歡迎大家轉至社區交流:
https://answer.uwa4d.com/question/5f8166d99424416784ef25b0
Q:我在Xcode真機調試中發現能耗始終處於Very High,而我項目的基本情況是(每幀GPU渲染3.5ms,每秒60幀,渲染解析度為750*1624,設備iPhone XS,場景中只有UGUI沒有其它3D或2D物體),麻煩大家幫忙看看這個電量消耗屬於正常嗎?還有沒有優化的空間(幀數和解析度估計是沒有辦法下降了,會影響項目效果),謝謝。
A1:測試過空場景Average Energy Impact也會顯示Very Hight(如下圖),題主的GPU能耗佔比較大說明CPU相對而言還是壓力比較小的:
這個帖子(https://gamedev.stackexchange.com/questions/177867/high-energy-consumption-in-empty-scene-unity-ios)也是類似的問題,看上去是因為Unity引擎本身相對於普通APP體量較大,所以能耗表現較高,降低目標幀率會有所改善。
Energy Impact表徵的是全局(非單個APP)的能耗,而且測試的時候USB連接充電是如何在統計中避免的不太清楚機制,建議使用Xcode Instruments工具的Energy Log模版測一下單個APP的能耗情況。
Energy Log文檔:
https://developer.apple.com/library/archive/documentation/Performance/Conceptual/EnergyGuide-iOS/MonitorEnergyWithInstruments.html
關於能耗的優化先關注整體的是GPU還是CPU(或其他方面),GPU的用FrameCapture定位一些比較高耗時的Shader進行優化,CPU結合Time Profiler模版定位一些高能耗的CPU Bound。
感謝羽飛@UWA問答社區提供了回答
A2:GPU的用FrameCapture定位一些比較高耗時的Shader進行優化。關鍵是Capture哪一幀,這個會很盲目。
感謝山中千年@UWA問答社區提供了回答,歡迎大家轉至社區交流:
https://answer.uwa4d.com/question/5f81af2d9424416784ef2642
封面圖來源於網絡
今天的分享就到這裡。當然,生有涯而知無涯。在漫漫的開發周期中,您看到的這些問題也許都只是冰山一角,我們早已在UWA問答網站上準備了更多的技術話題等你一起來探索和分享。歡迎熱愛進步的你加入,也許你的方法恰能解別人的燃眉之急;而他山之「石」,也能攻你之「玉」。
官網:www.uwa4d.com
官方技術博客:blog.uwa4d.com
官方問答社區:answer.uwa4d.com
UWA學堂:edu.uwa4d.com
官方技術QQ群:793972859(原群已滿員)
(長按識別二維碼進入UWA問答)
UWA發布 | Unity手遊性能藍皮書
近期精彩回顧【學堂上新】移動遊戲開發核心技術講解
【萬象更新】3分鐘就能掌握的視頻/音頻優化技巧
【學堂上新】Linux三劍客與Airtest的應用
【學堂上新】Console級寫實畫面遊戲的技術探索之路