Addressable卸載單個資源的疑問

1)Addressable卸載單個資源的疑問
​2)如何判斷硬件支持GPU Instance
3)StringBuilder反射實現String報錯
4)Unity 2018 RequireES3.1+AEP有什麼做用
5)Unity打包AssetBundle閃退html


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

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

Addressable

Q1:經過Addressable加載的Prefab A,裏面引用了Sprite A,如今經過Addressable加載Sprite B,把Sprite A釋放,替換爲Sprite B。ide

這時候Sprite A沒法經過Addressable.Releases釋放,提示Addressables.Release was called on an object that addressables was not previously aware of.Thus nothing is being released。測試

若是不釋放Sprite A,只是引用改成Sprite B,那麼在釋放Prefab A的時候是否會正常釋放Sprite A呢?優化

A1:Addressable內的Load和Release是配對調用的,第一步Load了Prefab A,對內部的Sprite A是Dependency引用,沒走Load流程,天然沒法經過Release釋放,能夠考慮,Prefab A不要直接掛Sprite A,也是經過運行時去Load Sprite A再掛,而後就能夠在須要的時候Release掉再替換B了。

這裏的細節是:網站

調用LoadAssetAsync時會調用TrackHandle,給Load的Completed事件添加一個OnHandleCompleted處理,這個處理內會將Load方法返回的Handle給保存到m_resultToHandle,在Release的時候去找這個Handle,並調用這個Handle.Release方法來作實際的Release操做。 ui

找不到,天然就報題主的錯誤了。spa

Q2:Prefab A不引用Sprite A,運行時再加載的方式會致使在編輯器非運行時沒法看到圖片,對於拼UI的同事會不太方便。我考慮的方案是,記錄當前資源是否運行時加載的,只有是才調用釋放,可是不肯定原來的Sprite A失去引用後,是否能在Prefab A釋放時正常釋放Sprite A。.net

A:我想通常來講你也是把Prefab A實例化之後使用,那麼2種狀況:

  1. 使用系統的Object.Instantiate,這時就和Addressable沒什麼關係了。Sprite A在切換時直接Destory就好了。
  2. 使用Addressables.ReleaseInstance,那麼系統會去調用AsyncOperationBase.DecrementReferenceCount,當引用計數爲0時,調用ResourceManager內部類的InstanceOperation.Destroy方法,最終調用到InstanceProvider.ReleaseInstance,這時你會發現系統其實也是簡單的Object.Destroy而已。

那麼咱們能夠這樣理解,對於Prefab A實例化出來的對象,由Addressbles管理,須要調用ReleaseInstance來釋放,當沒有引用的時候,系統Destroy它,那麼對於該對象內部的引用資源Sprite A,其實並非Addressable管理的那一層級。

最後整理一下:

  • 對於本身Instantiate出來的對象,Sprite A隨便何時均可以Destroy,和通常Unity對象作法同樣。
  • 對於經過Addressable實例化出來的對象,則能夠在須要切換Sprite的時候,調用Destroy方法釋放Sprite A,而後載入並設置Sprite B。
  • Sprite B若是使用Addressable來實例的,則在ReleaseInstance這個Prefab A實例化出來的對象前先調用ReleaseInstance方法釋放Sprite B。
  • 若是Sprite A的圖片資源並不在Prefab A所在AssetBundle包內,那麼是做爲依賴被載入的,理論上也是要在Prefab A實例被Release後,發現沒有引用的狀況下才Unload,也就是說,提早Destroy Sprite A並不會釋放它所用資源和AssetBundle包。
  • 最後仍是建議測試一下。

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


Rendering

Q:在國產安卓機上發現很多號稱支持ES 3.0的,可是實際上卻不支持GPU Instance,如今你們都是如何判斷硬件支持GPU Instance的?SystemInfo.supportsInstancing 仍是SystemInfo.graphiceDeviceType==OpenGLES3?

SystemInfo.supportsInstancing模擬器上調用這個接口,支持Instancing,但實際使用過程當中卻出現顯示問題,或者閃退的Bug。這個有什麼好的方式處理這種狀況嗎?

A1:建議使用SystemInfo.supportsInstancing,連接:
https://docs.unity3d.com/ScriptReference/SystemInfo-supportsInstancing.html

該問答由UWA提供

A2:上週也碰到了相似的問題,但願能對你有所幫助。
當時碰到的問題是:想在小米4上用GPU Instance,但Unity的接口SystemInfo.supportsInstancing居然是False, 去查了下,Mi4的CPU是驍龍801,GPU支持OpenGL ES 3.0的,理論上應該是支持的,有點奇怪,就去查了下Unity源代碼。

結論是:Unity內部對知足「Adreno GPU」和「OpenGL ES 3.0」這兩個條件的機器作了特殊處理。

至於Unity爲何要在這類機器上關閉Instance,註釋裏有解釋說是在這類GPU上,Uniform的效率慢,但這我就沒有作進一步驗證了,官方既然這麼處理了,相信應該是有他的道理。

因此邏輯上判斷是否支持Instance,仍是建議使用SystemInfo.supportsInstancing這個接口。

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

A3:目前已遇到的Instance的使用中有以下幾個狀況:

1.非AssetBundle的時候Instance沒問題,可是用了AssetBundle後,Instance失效。致使DrawCall大幅度變多。
緣由是:打AssetBundle的時候,Instance的變體被裁剪掉了,個人方法是對每一個Shader建立一個空的,打開Instance的材質球,將這些Shader和材質球打入一個AssetBundle,這樣變體就不會被裁減掉了。

2.PowerVR的GPU,當使用Instance的時候,直接閃退了。
緣由是:這是Unity 2018.4.18以前的一個Bug,在Unity 2018.4.18中修復了。
https://unity.cn/releases/full/2018/2018.4.18
Graphics: Fixed an issue with GPU instancing on PowerVR devices. (1156362)

因此聽上來,樓上遇到的問題和PowerVR的問題是同樣的,機器是支持Instance的,結果Unity 建立環境建立錯了。

因此,要麼就是模擬器設置問題,沒打開OpenGL ES3.0的支持,要麼就是Unity又犯了和PowerVR GPU同樣的錯誤。因此先檢查下模擬器的設置,若是沒問題能夠升級Unity試試。

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


Script

Q1:想經過反射的方式將StringBuilder轉換爲String來避免多餘的裝箱,但發現「_str」不存在,請問.net3.5以後應該用什麼替換「_str」,能夠實現Stringbuilder經過反射達到轉換成String的方式?

A:貌似已經改成"m_ChunkChars"了。

Q2:沒有再出現空異常,但強轉卻失敗了,是在使用反射的時候又出現什麼問題了嗎?
我是將值類型裝到StringBuilder並經過這種反射來轉成String類型的。

A:char[]類型不能強轉成String吧。能夠經過New String(char[])轉成String,但終歸是達不到你的需求的。

StringBuilder自己是能夠經過指定Capacity設置初始大小來避免中途擴容的。我想你是想避免ToString過程當中的內存分配。

反正你是經過反射來獲取到內部的ChunkChars來直接操做。乾脆在外部重寫一個ToString方法,ToString內部的這個str你能夠準備一個全局的,尺寸設置稍微大點。這樣是否是能夠達到你的目標。(我沒試過,提供一種思路參考。)

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


Build

Q1:大概知道Auto Graphics API是判斷設備是否支持OpenGL3的,若是不支持嘗試OpenGL2,可是線性空間下,只能選OpenGLES3,會多出來Require ES3.1和Require ES3.1+AEP。

想問下這兩個選項做用是什麼,會不會更加兼容更多設備?

A1:這兩個選項貌似是勾選後在Manifest裏面增長對ES3.1和ES3.1+AEP的Requirement,這樣若是是不兼容的設備在訪問Google Play Store時,該App就不會出現了。

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

A2:若是項目中用到了依賴ES3.1的特性,並且不支持Fallback,那麼能夠增長這個選項。好比用到了Compute Shader,但這樣會減小兼容的設備。

該問答由UWA提供


AssetBundle

Q1:咱們項目使用Unity 2018,在打包AssetBundle時會致使Unity閃退。嘗試過不少其它2018版本的Unity,依然沒有解決問題。下面是Unity閃退時的軟件報告:

https://uwa-public.oss-cn-beijing.aliyuncs.com/answer/attachment/public/101067/1594881341141.unityCrash

A:去掉以下圖的設置就正常了:

感謝題主廖武興@UWA問答社區提供了回答

A2:我沒看你的Crash文件,我先說Unity 2018打包會閃退的最多見的狀況吧。

Unity 2018新增的Prefab嵌套引用機制,若是嵌套引用的對象丟失,會閃退,好比你把模型文件xx.FBX存成關聯引用的prefab,xx.prefab,而後刪除xx.FBX,打包會閃退。斷掉關聯就不會了。

另外樓上回答的Bundle打包時候存在嵌套循環引用,並不會引發打包失敗,只是加載的時候會出問題。項目恰好出現了。仍是拿模型舉例:A.ab 打包了模型貼圖, B.ab打包了模型的動做文件,a.prefab(打包在A.ab)跟b.prefab(打包在B.ab)都引用了這些貼圖跟動做文件。

感謝簡單就好@UWA問答社區提供了回答

封面圖來源於網絡


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

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

相關文章
相關標籤/搜索