本地資源檢測,特效檢測中Overdraw相關問題

1)本地資源檢測,特效檢測中Overdraw相關問題
​2)Android上如何加速判定Bundle文件是否存在
3)xLua pcall異常捕獲
4)Mipmap和帶寬
5)Timeline卡頓嚴重時,Clip被完全跳過沒有執行




這是第230篇UWA技術知識分享的推送。今天我們繼續爲大家精選了若干和開發、優化相關的問題,建議閱讀時間10分鐘,認真讀完必有收穫。

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

Rendering

Q:咱們這個特效資源檢測Overdraw和實際檢測差距有點大。是不是統計峯值比較好一些?有可能一個特效播放時間特別長,但是峯值就很短的時間,這樣一平均Overdraw就很低了。

 

 

A:首先要談談Overdraw的定義問題:

1. Overdraw是一個描述像素重複繪製次數的概念。單個像素的重複繪製次數很容易理解,但是對於一個特效的Overdraw,筆者還沒有找到什麼公認的“標準”的計算公式,也不存在什麼“官方”的定義。

對於一幀來說,Overdraw值可以定義爲該幀總體繪製像素的次數 / 屏幕上實際繪製的像素數。而這個值也不能簡單理解爲“繪製的層數”。(試想如果總共在屏幕上繪製了1000個像素,其中只有一個像素繪製了10層,那這個重複繪製的像素對Overdraw值得貢獻也是可以忽略的,計算結果爲:1009/1000=1.009)。而對於整個特效播放過程中的Overdraw,具體公式如何定義,又是一個問題。

2. sunbrando的開源庫的計算方法:整個播放過程中,

分子是對每一幀繪製像素的次數求和,分母是對每一幀屏幕上實際顯示的像素數求和。

這個公式確實可以從整體上衡量一個特效播放過程中的Overdraw。但是這種計算存在這樣一個問題:有些幀特效佔屏幕的比例很大,有些幀特效佔屏幕的比例很小,而運算結果受屏幕佔比大的幀影響比較大。比如第一幀繪製了1000個像素,只繪製了1層,而第二幀繪製了2個像素,繪製了10層,那麼計算出的值爲:(1000x1 + 2x10) / (1000 + 2) = 1.018 。

UWA本地資源檢測對特效Overdraw的計算與上述開源庫計算公式是相同的,不同的是特效播放的邏輯與相機對準的方式。

影響兩個工具計算結果不同的因素有:

  1. 相機的對準方式不同。UWA的工具有一套相機自動對準的邏輯,相機的擺放不同,會造成Overdraw不同。
  2. 播放的時機不同。UWA的工具會創建好場景後,自動加載並實例化特效,進行播放。而開源庫ParticleEffectProfiler的方案是先把特效放到場景中,啓動場景後再執行相關的邏輯,進行檢測。

樓主的案例中,除了相機對準方式不同導致兩個工具計算結果不同之外,很大程度上受到了獲取的特效播放時機的影響。

使用開源庫工具進行檢測,發現抓取相機的Overdraw數據前,已經進行了三次Update,如下圖所示。也就是說,特效的Overdraw是從第4幀開始統計的。這與該工具的代碼邏輯有關,就不對原因進行分析了。

而前三幀恰恰又是在數值上貢獻最大的幀,如下圖所示,前三幀特效中有一個面片佔了很大的屏幕空間。

而第四幀開始,特效的像素佔比就小了很多。

這是兩個工具即使使用相同的對準方式,Overdraw計算結果也不相同的原因。

另外,UWA的特效檢測還存在一個問題:相機視錐體的Size是不斷調整的,那麼不同的幀特效的屏幕佔比會因此而改變,像素的繪製量也不同,對上述Overdraw值計算公式的貢獻也就不一樣。也就是說,相機的Size越小的幀,特效屏幕佔比越大,對結果的影響越大。

這裏有兩套解決方案:

  1. 換公式,每幀都計算出OverdrawRate,再求平均。
  2. 用戶自定義相機,相機的視錐體保持固定,這樣就是放棄自動對準,使相機的設置更接近用戶的實際使用環境。

UWA的工具會不斷迭代,根據需求儘可能找到一套最佳策略來幫助開發者對項目進行規範。

如果在優化中要使用工具進行檢測,並衡量優化的結果,建議使用一套工具即可。使用同一套標準至少可以對資源的性能進行一個排名,據此來選擇優化的優先級,並使用同一套標準評估優化結果。

感謝Prin@UWA問答社區提供了回答,歡迎大家轉至社區交流:
https://answer.uwa4d.com/question/5fc7171310a17c6c2b09d47b


AssetBundle

Q:我們在Android平臺上打包時,把Bundle放到Streaming Assets中,Patch文件放到持久化目錄中。在啓動時判斷:Patch目錄有Bundle就用Patch目錄的,沒有就看Streaming Assets目錄有沒有。

問題是:Android判斷Streaming Assets下是否有文件,要用www或UnityWebRequest。這兩種都是異步讀文件,等待異步操作結束需要幾毫秒以上,導致判斷邏輯耗時很長(Bundle 較多)。

想請教下大家是怎麼處理 Android上的文件判定問題呢?

A1:Streaming裏放個資源字典文件,用這個判斷。

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

A2:可以這樣來處理:
有一個全局的Bundle資源的配置文件,裏面記錄了所有Bundle的信息,這裏面會包含其相對路徑。只有從包裏面讀這個文件是需要異步的,如果從Patch目錄讀這個文件也是同步的(例如使用FileStream)。

得到了所有Bundle的相對路徑後,在實際需要加載某Bundle時,先使用File.Exist或者直接判斷AssetBundle.LoadFromFile的返回值是否爲null來判斷Patch目錄是否有該Bundle,如果沒有的話再使用包內路徑重新調用AssetBundle.LoadFromFile即可。

經測有效,把文件判斷分散開,Patch目錄可以直接用File,不存在就認爲是在Streaming Assets目錄,最後利用Load的結果來更新,看是否存在的記錄。

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

A3:有一個不錯的開源庫,能夠同步讀取StreamingAssets下的文件:
《BetterStreamingAssets》

感謝張迪@UWA問答社區提供了回答,歡迎大家轉至社區交流:
https://answer.uwa4d.com/question/5fc9ad5a10a17c6c2b09d4f9


LUA

Q:想請問下在xLua中使用pcall/xpcall實現C#中的Try Catch功能的時候,在iOS/Android/模擬器等平臺上,有什麼需要注意的地方。

由於對Lua底層不是很瞭解,想確認下,線上項目使用是否可行。還有這個的性能消耗有多少,Update裏可以用嗎?

項目使用的是xLua,版本是2.1.14,Unity版本是2019.4。

A:大範圍的使用中,pcall和xpcall本身肯定有一定的性能影響,不過我們倒是沒有做過很完備的性能測試對比。印象中之前做過一些檢索,沒有找到特別明確的答案。

Lua中源碼的實現對比可以參考這裏:
https://stackoverflow.com/questions/16642073/whats-the-difference-behind-normal-function-call-and-pcall/16642612

可以看到pcall的確比常規的call多做了一些事情,只是這是Lua做異常捕獲的唯一方式,當你不想遊戲邏輯被錯誤信息打斷的時候,只能使用它。

pcall/xpcall在各種平臺和模擬器上除了略微的性能影響之外沒有任何問題,因爲它是Lua原生的方式,如果使用LuaJIT,注意一下Lua和LuaJIT下的區別封裝即可。

感謝賈偉昊@UWA問答社區提供了回答,歡迎大家轉至社區交流:
https://answer.uwa4d.com/question/5fc4bcbd10a17c6c2b09d3ca


Rendering

Q1:請問,Mipmap究竟能不能降低帶寬,如果不能降低,能否詳細告訴一下原因,謝謝。

A1:可以降低!
Mipmap是爲了解決Texel和Pixel沒有1:1對應的一種處理方式。一般來說如果處理遠處物體的渲染,依然使用正常的紋理採樣,那麼其實1個Pixel就一般需要採樣到多個不相鄰的Texel[1:n的關係],那麼不相鄰這就可能涉及到一個Cache Miss的問題。而Cache Miss必然需要從顯存中重新採樣紋理數據,這自然就會消耗帶寬。

感謝會丟鍋的Coder@UWA問答社區提供了回答

A2:是可以降低帶寬開銷的。
主要是由於在渲染相鄰Pixel的時候,採樣的Texel可能是在內存中不連續的,而GPU的Texture Cache是很小的。

如果沒有Mipmap,在渲染遠處物體時,GPU可能需要不停的在儲存Texture的各段Memory不停的訪問,Cache Miss很嚴重。而使用了Mipmap後,相當於離線將每個Texel覆蓋的Texture的面積變大,這樣可以提升Texture Cache的命中率,從而減少直接從內存讀取數據的次數,從而節省了帶寬的開銷。

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

Q2:請問上文中:
1. “而使用了Mipmap後,相當於離線將每個Texel覆蓋的Texture的面積變大”,這裏是Pixel還是Texel?
2. 還有就是Memeory是指內存是吧?不是已經把一張圖提交給了GPU顯存了嗎?

A:可以看下我知乎的這個回答,解決你對Pixel和Texel的疑惑:
《shader 中,fwidth 或者說 ddx/ddy 到底是什麼意思?》

感謝止戈@UWA問答社區提供了回答,歡迎大家轉至社區交流:
https://answer.uwa4d.com/question/5fc61e1410a17c6c2b09d433


Timeline

Q:Timeline,如果在播放時卡頓嚴重,會出現前面位置的Clip被完全跳過沒有執行,有沒有人碰到過類似的問題?

Timeline 信號的這個描述,是不是即使信號跳過了,依舊會執行?
The Retroactive property, when enabled, will trigger the signal if the timeline begins playing after the signal’s time.
The Emit Once property, when enabled, will trigger the signal only once when the timeline loops.

 

A:勾上之後是會執行,具體邏輯可參考TimeNotificationBehaviour腳本(Timeline中Signal Track的mixer邏輯腳本),如下做了簡單註釋:

 

如果需要倒放也會Trigger,也可以參考這個擴展自己的Timeline。

感謝羽飛@UWA問答社區提供了回答,歡迎大家轉至社區交流:
https://answer.uwa4d.com/question/5fc5ff6310a17c6c2b09d42d

封面圖來源:Barracuda Style Transfer code sample


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

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



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章