關於Addressable的疑問

1)關於Addressable的疑問
2)Addressable如何進行熱更新
3)如何設置SceneView相機的Shader變量
4)Activity默認爲SingleTask的原因
5)關於Resources.UnloadUnusedAssets調用時間過長的問題


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

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

 

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(原羣已滿員)

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