URP關於多個攝相機的性能優化

1)URP關於多個攝相機的性能優化
​2)Unity Addressables打包的時候如何設置BuildAssetBundleOptions.DisableWriteTypeTree
3)Unreal能夠用於商業化遊戲的熱更新方案
4)UGUI SpriteAtlas在使用中回調實例化,AtlasRequested和Start的順序顛倒
5)從AssetBundle中動態加載渲染管線,後期渲染異常問題
git


UWA 問答社區:answer.uwa4d.com
UWA QQ羣2:793972859(原羣已滿員)
github

Rendering

Q1:URP7.4.3,除開主相機外,還有一個子相機,用於將照到的模型渲到遊戲主界面UI上。在Profiler中看到如下狀況:性能優化

能夠看到,在子相機中也進行了包括對LOD的計算,但子相機的CullingMask只開了一個名爲RTModel的Layer,在這一層裏只有一個3D對象。按說子相機CullScriptable這塊開銷不該該有才對。網絡

目前懷疑可能的緣由是URP會對每一個Base Camera都進行這部分的計算,但若是用Overlay相機,又沒法用原來的方式將相機的targetTexture渲到一張RawImage上了。框架

有人遇到過麼?編輯器

A:題主的疑惑是:子相機的CullScriptable這塊的開銷不該該有那麼大對吧(畢竟我只有一個物件)?函數

這裏有兩個問題:
1.Culling到底作了啥,只有一個物件爲啥要Culling那麼久(難道只有一個物件也要作不少的準備工做)?
2.你在Profiler裏面看到的數據真的是真實數據嗎?也就是說,子相機的Culling真的作了1.68ms嗎?
工具

拋開這兩個問題,也能夠有更好的作法:oop

咱們一共兩個相機,主相機和UI相機,那麼UI上顯示的3D物件怎麼辦呢?
咱們有個虛擬相機,所謂相機,其實就是作一個VP矩陣,作一個RT,繪製可見的物件就能夠了。那麼使用Unity的SRP,隨便在什麼地方,設置一下VP矩陣,設置RT,接着繪製指定的物件(UI中全部的3D物件都會掛在這個物件下面),而後這個RT就能夠隨意使用了。
性能

假如一個UI上有兩個3D物件,儘可能都放在一個RT上,若是不行,就放在兩個或更多的RT上。只是會多幾個繪製命令,幾個RT(還不須要是全屏的),並且會多幾個Swap RT的操做。因爲咱們項目沒需求須要若干RT,因此假設一下,在這種須要若干RT的狀況下,也能夠用一個RT加多個Viewport來解決的。這個代碼都是現成的,參考一下Cascade Shadow Map的作法,這樣Swap RT也就省了。

綜上所述,既然你都知道本身要繪製什麼,就不要給Unity Culling的機會了。

感謝王爍@UWA問答社區提供了回答

Q2:數據是在Development Build中連真機看到的性能數據, 目前在使用相似於HLOD的方式來減小掉這個LOD的巨大開銷。樓上說的「設置一下VP矩陣,設置RT」,請問這個VP矩陣的操做具體是什麼?能否詳解下或者有相關資料嗎?

A:一切皆有可能!但不過這個不重要。而後你提的HLOD和LOD和上面的Culling不要緊。VP矩陣就是view矩陣和projection矩陣。相機的做用就是提供這倆矩陣的。

若是你在管線裏面設置了相應的矩陣,而後繪製指定的物件,就能夠徹底不用多一個相機,畢竟多一個相機就多一個Culling。

若是你對VP矩陣不熟悉,不清楚怎麼實現,也簡單。依然用一個額外相機,關上這個相機的Culling,而後在渲染pass中,不要繪製cullingresult.visibleobject,而直接用Graphics.DrawMesh或者CommandBuffer.DrawMesh繪製你要顯示的那個3D Object的物件就行了。

感謝王爍@UWA問答社區提供了回答


Addressable

Q:原來的AssetBunlde打包的時候能夠設置BuildAssetBundleOptions.DisableWriteTypeTree,使得包體小好多。今天項目嘗試升級使用Addressables,請問該如何設置BuildAssetBundleOptions.DisableWriteTypeTree?

A1:首先Addressable打Bundle包主要的腳本是BuildScriptPackedMode,在DoBuild函數內能夠看到用了AddressableAssetsBundleBuildParameters這個類,這個類繼承於BuildParameters,而BuildParameters有一個成員變量是public ContentBuildFlags ContentBuildFlags { get; set; },這個ContentBuildFlags就是用於設置DisableWriteTypeTree的,BuildParameters是屬於ScriptableBuildPipline的。

參考SBP的CompatibilityBuildPipline有如下操做:

if ((options & BuildAssetBundleOptions.DisableWriteTypeTree) != 0) parameters.ContentBuildFlags |= ContentBuildFlags.DisableWriteTypeTree; IBundleBuildResults results; ReturnCode exitCode = ContentPipeline.BuildAssetBundles(parameters, content, out results);

咱們在BuildScriptPackedMode.cs裏也能夠加上:

var buildParams = new AddressableAssetsBundleBuildParameters( aaContext.Settings, aaContext.bundleToAssetGroup, buildTarget, buildTargetGroup, aaContext.Settings.buildSettings.bundleBuildPath); buildParams.ContentBuildFlags = UnityEditor.Build.Content.ContentBuildFlags.DisableWriteTypeTree;

可是我在這兒測試了一下,並無什麼用,不知道是最底層沒有支持仍是個人測試用例有問題。建議用一樣的方法,測試一下。

另外說一下,我看了一圈代碼,在打包和壓縮部分SBP並無用到這個參數。而在處理場景依賴的地方,這個參數會被合到BuildSettings結構體提供給C++部分調用。因此這個參數應該最終傳到C++層起做用。

感謝黃程@UWA問答社區提供了回答

A2:Addressable彷佛沒有給外部的接口直接來修改這個設置項,應該是須要本身寫代碼來修改打包方式了。須要本身寫一個BuildMode,能夠參考如下這個帖子中第五個問題的回答:https://answer.uwa4d.com/question/5e649911438f7d0db495c724#5e64a4e8438f7d0db495c725

核心的代碼是要DoBuild中修改buildParams的設置項,buildParams.ContentBuildFlags |= UnityEditor.Build.Content.ContentBuildFlags.DisableWriteTypeTree;以下圖:

作了一下測試,發現是有效果的:

上面是默認的打包,修改後從新打包,變成下面的結果:

總體都變小了一點點,並且使用解開AssetBundle後,能夠看到裏面的內容變得很簡潔。

 

感謝Xuan@UWA問答社區提供了回答


Unreal

Q:Unreal方面,目前有什麼能夠用於商業化遊戲的熱更方案嗎?

A1:由於咱們公司是本身研發的一套框架,因此我也沒有太在乎是否有開源的Unreal熱更新方案,印象中好像是沒有的。

但基於Unity引擎的開源方案卻是蠻多,大家能夠按照Unity的開源方案的思路實現一套,基本思路就是使用反射預先生成引擎的導出Lua接口。

如何利用反射呢?簡單來講就是根據反射獲得引擎接口的函數名,返回值類型、參數名和參數類型,由工具生成解析參數類型以及它的個數和順序,返回正確結果的Lua導出函數int xxx(lua_State *L) 函數。對於類成員函數須要導出到Table裏,根據C++類層級關係利用Metatable能夠找到父類的Lua導出成員函數。

Unity開源方案如此,Unreal也能夠如此,區別只是Unreal使用UClass UProperty這套,而Unity使用C#而已。大家能夠嘗試着實現一下。

感謝王遠明@UWA問答社區提供了回答

A2:能夠參考如下這個連接:
https://github.com/Tencent/puerts

感謝lanyt@UWA問答社區提供了回答

A3:騰訊有兩款Lua熱更新的框架可供使用:

  1. sLuaUnreal
    聽說是《和平精英》手遊採用的框架;

  2. UnLua
    較sLua後推出的一個框架。

感謝Vest@UWA問答社區提供了回答


Script

Q:請問UGUI SpriteAtlas使用中,AtlasRequested和Start的順序顛倒,以下圖:

測試工程可戳原問答獲取,測試環境Unity 2019.4。

A:可使用Timeline看到具體的執行時機,在Main.Update裏面進行實例化的時候(我測試的時候把Main.Update裏面的interval去掉了),Atlas的回調跑到第二幀了,而TestAtlasSprite的Awake、OnEnable和Start都在第一幀。在Main.Start裏面實例化的時候,這些打印都在第一幀,由於Atlas的回調是在EarlyUpdate.SpriteAtlasManagerUpdate裏面,而實例化出來的TestSpriteAtlas.Start是在FixedUpdate.ScriptRunDelayedFixedFrameRate下面的,因此就跑到了Atlas回調的後面。

這個圖是在Update裏面執行的狀況。

 

這個是在Start裏面執行的狀況,能夠看到都是在第一幀打印的。

 

這是在Main.Start裏面執行實例化的Timeline的圖,能夠看到TestSpriteAtlas.Start是在Atlas的回調後面執行的。

 

這是在Main.Update裏面執行實例化的Timeline。

EarlyUpdate,FixedUpdate這些回調的執行順序能夠參考:
https://medium.com/@thebeardphantom/unity-2018-and-playerloop-5c46a12a677

感謝Xuan@UWA問答社區提供了回答


Rendering

Q:有人遇到動態切換管線,顯示錯誤的問題嗎?
現有UBP項目需求在進入新的場景以後,切換到指定的渲染管線。在打包場景的時候將渲染管線一併打包到場景中,並經過如下代碼來切換渲染管線。

GraphicsSettings.renderPipelineAsset = targetAsset; QualitySettings.renderPipeline = targetAsset;

可是經過AssetBundle加載出來的渲染流程:在後處理中,UberPost 缺乏兩個Keyword。

形成以下的圖像。

在Project Setting -》 Quality裏面手動設置成項目的hero_show管線則正常顯示。

經過斷點調試發現:在Render過程當中,Keywords其實都是有賦值的。兩者的流程均一致。

在PostProcessPass.cs文件中:

void Render(CommandBuffer cmd, ref RenderingData renderingData)

但就是在Frame Profiler中抓幀顯示沒有Keywords。附上簡單的項目測試:

默認是Windows平臺。直接運行defaultScene便可。
如不是,按下面流程處理:
1. AssetBundle->build
2. 運行defaultScene.

連接:https://pan.baidu.com/s/1q3s6mAUwE723wTJ3VmS81g
提取碼:8kwn

A1:雖然沒遇到過,可是能猜到緣由。
先總結一下樓主的問題:
Project Setting -》 Quality裏面手動設置渲染管線,顯示正常;
以AssetBundle的形式加載渲染管線,顯示不正常,緣由是Keyword丟失。

那麼答案就很簡單了。
由於這兩種模式Unity對渲染管線這個資源的處理方式是不一樣的:
以第一種方式,Unity會認爲渲染管線是個默認資源,將其所有打包進包體,並進行使用。
以第二種方式,Unity會將渲染管線,特別是渲染管線關聯的Shader,判斷其Keyword是否被使用,若是沒使用,就優化掉了。

項目尚未看,我猜想樓主是在代碼中開啓的這兩個Keyword,這種代碼開啓Keyword的方式,Unity檢測不到,因此就丟掉了。

解決方法也簡單,對付Keyword經常使用的方案,建立一個沒用的材質球,使用相應的Shader,在材質球中開啓對這些Keyword的使用打進AssetBundle,這樣Unity就知道,這個Shader的這些Keyword是有用的,就不會Skip掉了(其實這個方法常被用於以防instance_on這個Keyword丟失)。

感謝王爍@UWA問答社區提供了回答

A2:想嘗試樓上的方法,發現材質球並不能直接引用到UberPost這個Shader,由於這個Shader是放在Package目錄下,因而參考了Packages目錄下Shader打包這個帖子中的方法進行打包。使用編輯器的SVC採集方法採集了一下SVC,SVC裏面的UberPost是有那兩個Keyword的。將UberPost和這個SVC一塊兒打包,拆包後能夠看到ubqScene場景是引用了剛剛這個SVC中的Shader的,切場景後在Awake裏面加載SVC並Warmup,然而也仍是沒有解決問題。最後我把題主的原始工程打了一個exe,運行發現並無Keyword丟失的問題,渲染一切正常。另外打包成APK測試,在小米9上測試也是正常渲染的。

可能仍是Unity編輯器的問題吧,相似於這個帖子:
UnityEditor下加載AssetBundle,材質球Keywords正常,可是某些屬性不存在)。

感謝Xuan@UWA問答社區提供了回答

封面圖來源於網絡


今天的分享就到這裏。固然,生有涯而知無涯。在漫漫的開發週期中,您看到的這些問題也許都只是冰山一角,咱們早已在UWA問答網站上準備了更多的技術話題等你一塊兒來探索和分享。歡迎熱愛進步的你加入,也許你的方法恰能解別人的燃眉之急;而他山之「石」,也能攻你之「玉」。

官網:www.uwa4d.com
官方技術博客:blog.uwa4d.com
官方問答社區:answer.uwa4d.com
UWA學堂:edu.uwa4d.com 官方技術QQ羣:793972859(原羣已滿員)

相關文章
相關標籤/搜索