1)關於Addressable的疑問
2)Addressable如何進行熱更新
3)如何設置SceneView相機的Shader變量
4)Activity默認為SingleTask的原因
5)關於Resources.UnloadUnusedAssets調用時間過長的問題
Addressable
Q:最近幾天在看Addressable,雖然未完全看懂,但感覺這相比AssetBundle好用得多,也考慮得很周全。主要是在參考官方文檔Addressables 1.6.2時,有一些疑問:
1. 相對AssetBundle,它的打包顆粒度如何控制的?比如說,AssetBundle可以自己控制多個資源打到一個AssetBundle中。
2. 有沒有腳本可以自動設置Addressable名稱以及Label?畢竟稍具規模的項目,資源量也不小,手工設置過去也不科學。
3. 關於Check for Content Update Restrictions,官方文檔上有這樣一句話:Note:This command will do nothing if all your changes are confined to non-static groups,也就是說這個檢查對非靜態Group不起作用。問題是,在哪里定義這個Group?它是non-static還是static呢?
4. 關於Unique Bundle IDs,官方文檔上也是Turn on“Unique Bundle IDs”within the AddressableAssetSettings Inspector,但我沒有找到。
A1:第一個問題:Addressable最終也是打包成AssetBundle,打包的存儲目錄由每個Group的BundledAssetGroupSchema設定的Build Path而定。對於同一個Group的資源是否打包到一個Bundle里面,也是由BundledAssetGroupSchema的Budle Mode決定的。如果是Pack Together,則會打包到一個Bundle里,Pack Separately則會將每個Entry打成一個Bundle。關於粒度問題跟使用Asset Bundle是類似的,Addressable會自動管理Bundle包的依賴關系,如果依賴的資源沒在其它的Bundle包里面,則會被自動打進自身的Bundle里面。
第二個問題可以參考圖片里面的做法:
![]()
感謝Xuan@UWA問答社區提供了回答
A2:問題3:
![]()
Cannot Change Post Release == static
Can Change Post Release == non-static
問題4:
![]()
關於更多Addressable的技術話題,可查閱UWA學堂相關課程:
《Addressable系統解析及實踐經驗》
《Addressable進階實用方法》
感謝黃程@UWA問答社區提供了回答,歡迎大家轉至社區交流:
https://answer.uwa4d.com/question/5e649911438f7d0db495c724
Addressable
Q:請教一下Adressable如何進行熱更新。在之前的項目中,所有的資源打包成AssetBundle放在StreamingAssets里,有更新的AssetBundle會下載到可寫目錄,游戲加載時優先加載可寫目錄的AssetBundle。
那么在Addressable中如何實現這個功能呢?能否設置優先讀取目錄?
A:不知道題主說的設置優先讀取目錄是指什么意思,暫時按照自己理解的意思來說一下。Addressable的資源更新功能需要在Editor和Runtime兩方面處理。在Editor的部分,需要在Setting里面勾選Build Remote Catalog,第一次使用New Build后會產生Catalog文件(.hash和.json文件),這兩個Catalog文件和打出來的Bundle文件需要放在服務器上。之后再進行資源更新需要Update a Previous Build來進行打包。這時候Editor會覆蓋掉原來的Catalog文件(.hash和.json文件),同時會有新的Bundle文件生成,將新生成的文件替換服務器原來的文件即可。
在Runtime的部分,需要調用CheckForCatalogUpdates和UpdateCatalogs來更新資源。當資源更新到本地后,再調用Addressable.LoadAssetAsync則會自動從本地目錄進行加載了,不知道這里的本地目錄是不是就是題主所說的優先目錄。
具體代碼可以參考:
https://answer.uwa4d.com/question/5e3b7fe686a39548919837e1
感謝Xuan@UWA問答社區提供了回答,歡迎大家轉至社區交流:
https://answer.uwa4d.com/question/5e64aa06438f7d0db495c727
Camera
Q:做一個效果需要設置一個WorldToView矩陣,掛了一個腳本在主相機上設置了全局的變量,但是在SceneView下仍然使用的是主相機的WorldToView矩陣,有什么辦法在SceneView渲染時設置SceneView的Camera的屬性呢?
A:如果是想把GameView的鏡頭同步到SceneView,可以嘗試以下方法:
[InitializeOnLoad] public static class SyncSceneViewMenuItem { private const string MenuName = "Tools/同步GameView鏡頭到SceneView"; private static bool enabled; static SyncSceneViewMenuItem() { SyncSceneViewMenuItem.enabled = EditorPrefs.GetBool(MenuName, false); this.Apply(); } [MenuItem(MenuName)] public static void ToggleSync() { SyncSceneViewMenuItem.enabled = !SyncSceneViewMenuItem.enabled; EditorPrefs.SetBool(MenuName, SyncSceneViewMenuItem.enabled); this.Apply(); } private void Apply() { Menu.SetChecked(MenuName, SyncSceneViewMenuItem.enabled); SyncSceneViewCamera.enabled= SyncSceneViewMenuItem.enabled; } }
public class SyncSceneViewCamera : MonoBehaviour { #if UNITY_EDITOR public static bool enabled; private Camera camera; private void Update() { if (SyncSceneViewCamera.enabled) { if (this.camera == null){ this.camera = Camera.main; } UnityEditor.SceneView.lastActiveSceneView?.AlignViewToObject(this.camera.transform); } } #endif }
感謝黃程@UWA問答社區提供了回答,歡迎大家轉至社區交流:
https://answer.uwa4d.com/question/5d52a35f80d96a06d776dc55
Android
Q:Unity導出的Gradle項目,默認會把UnityPlayerActivity配置成SingleTask。但是實際測試中,有不少第三方SDK會沖突SingleTask的配置。
Unity使用這個默認配置是否有什么設計原因?如果修改到Standard會有一些什么陷阱?
A1:主要是為了防止游戲被啟動導致二次崩潰,但是只依賴LaunchMode為SingleTask是不夠的,確實會有第三方SDK強制要求按他們的來,比如騰訊渠道就要求SingleTop:
游戲的Activity的LaunchMode需要設置為SingleTop,設置為SingleTop以后在平台拉起游戲的場景下,有可能會出現游戲Activity被拉起兩個的情況,所以游戲Activity的onCreate里面需要檢測當前Activity是否是重復的游戲Activity,如果是則要結束當前游戲Activity。
所以兩手准備比較萬全,能用SingleTask的用SingleTask,不行的就用靜態變量來做下判斷。
感謝littlesome@UWA問答社區提供了回答A2:這個對於降低宕機數的統計有一定的貢獻,很多時候你的游戲沒有設置成SingleTask切換后台再次回到游戲,可能就會被重新拉起來,這就加大了你的宕機統計,對宕機率影響挺大的。
感謝李星@UWA問答社區提供了回答,歡迎大家轉至社區交流:
https://answer.uwa4d.com/question/5e5e1c29438f7d0db495c6b8
Resource
Q:游戲中有上百個皮膚、坐騎、翅膀等外觀展示Prefab,這些Prefab的加載方式均是通過AssetBundle加載,當創建出Prefab后,會調用AssetBundle.Unload(false)來卸載掉AssetBundle,但GameObject和相應的資源還會在內存中保存着。
現在遇到的問題是:在手機上全部點開這些外觀模型后,第一次調用Resources.UnloadUnusedAssets時,會產生一個可能長達20秒的卡頓。如果那些GameObject均已Destroy掉,且內存中這些相應的資源全部變成垃圾待回收了,調用Resources.UnloadUnusedAssets會卡這么長時間還可以理解,但現在問題是這些資源都還引用着,不會被這個API清理嗎?有確認過不是因為其它的資源引起的,甚至AssetBundle.Unload(false)這個接口都試過屏蔽掉,相同操作下同樣會產生卡頓。
請問導致這個超長卡頓可能的原因有哪些?Unity版本為2017.4.30f1。
最新進展:測試加載單個Prefab資源后(調用完AssetBundle.LoadAsset),不調用任何其它釋放的接口,直接調用c,在調試日志中相關顯示為:
Unloading 27 unused Assets to reduce memory usage. Loaded Objects now:6777.
Total: 20.391873 ms(FindLiveObjects: 1.497475 ms CreateObjectMapping:0.186901 ms MarkObjects: 15.905487 ms DeleteObjects: 2.801631 ms)
現在最大的問題就是:這個27是怎么來的?它是哪些資源被標記為垃圾然后刪除了?
A:20秒的情況下,是否有對應的日志?看看4個步驟里哪個步驟耗時久,還有Objects是什么數量級。
你的測試代碼可以改成這樣試試:
yield return Resources.UnloadUnusedAssets(); yield return Resources.UnloadUnusedAssets(); // 確保這一條的輸出是 Unload 0 個 var info0 = CreateIDToInfoMap(Resources.FindObjectsOfTypeAll<Object>()); // 創建一個字典,Key是InstanceID,Value是對象描述 ab.LoadAsset(); yield return Resources.UnloadUnusedAssets(); var info1 = CreateIDToInfoMap(Resources.FindObjectsOfTypeAll<Object>()); // 對比info0和info1 把描述打印出來,就可以知道少了哪些Object
感謝littlesome@UWA問答社區提供了回答,歡迎大家轉至社區交流:
https://answer.uwa4d.com/question/5e64e0e6438f7d0db495c72b
今天的分享就到這里。當然,生有涯而知無涯。在漫漫的開發周期中,您看到的這些問題也許都只是冰山一角,我們早已在UWA問答網站上准備了更多的技術話題等你一起來探索和分享。歡迎熱愛進步的你加入,也許你的方法恰能解別人的燃眉之急;而他山之“石”,也能攻你之“玉”。
官網:www.uwa4d.com
官方技術博客:blog.uwa4d.com
官方問答社區:answer.uwa4d.com
UWA學堂:edu.uwa4d.com
官方技術QQ群:793972859(原群已滿員)