Unity 加載線程控制-防止線程造成的卡頓

Unity 加載線程控制

1. 加載線程說明

Unity 允許開發(fā)者控制用于加載數(shù)據(jù)的后臺線程的優(yōu)先級。這一點對于嘗試在后臺將 AssetBundle 流式傳輸?shù)酱疟P時尤為重要。
主線程和圖形線程的優(yōu)先級都是 ThreadPriority.Normal;任何具有更高優(yōu)先級的線程都會搶占主線程/圖形線程的資源并導(dǎo)致幀率不穩(wěn),而優(yōu)先級較低的線程則不會。如果任何線程與主線程具有相同的優(yōu)先級,則 CPU 會嘗試為這些線程提供相同的時間,在多個后臺線程執(zhí)行繁重操作(例如 AssetBundle 解壓縮)的情況下,這通常會導(dǎo)致幀率卡頓。
目前,可在三個位置控制該優(yōu)先級。
首先,資源加載調(diào)用(如 Resources.LoadAsyncAssetBundle.LoadAssetAsync)的默認優(yōu)先級來自于 Application.backgroundLoadingPriority 設(shè)置。如文檔所述,此調(diào)用還限制了主線程用于集成資源的時間(注意: 大多數(shù)類型的 Unity 資源都必須“集成”到主線程上。集成期間將完成資源初始化并執(zhí)行某些線程安全操作。這包括編寫回調(diào)調(diào)用(例如 Awake 回調(diào))的腳本。請參閱“資源管理”指南以了解更多詳細信息,從而限制資源加載對幀時間的影響。
其次,每個異步資源加載操作以及每個 UnityWebRequest 請求都返回一個 AsyncOperation 對象以監(jiān)控和管理該操作。此 AsyncOperation 對象會顯示 priority 屬性,該屬性可用于調(diào)整各個操作的優(yōu)先級。
最后,WWW 對象(例如從 WWW.LoadFromCacheOrDownload 調(diào)用返回的對象)會顯示threadPriority 屬性。請務(wù)必注意,WWW 對象不會自動使用 Application.backgroundLoadingPriority 設(shè)置作為其默認值;WWW 對象總是被默認為 ThreadPriority.Normal
值得注意的是,用于底層系統(tǒng)在處理解壓縮和加載數(shù)據(jù)時,不同 API 之間存在差異。Resources.LoadAsyncAssetBundle.LoadAssetAsync 由 Unity 的內(nèi)部 PreloadManager 系統(tǒng)進行處理,該系統(tǒng)可管理自己的加載線程并執(zhí)行自己的速率限制。UnityWebRequest 使用自己的專用線程池。WWW 在每次創(chuàng)建請求時都會生成一個全新的線程。
雖然所有其他加載機制都有內(nèi)置的排隊系統(tǒng),但 WWW 卻沒有。在大量經(jīng)過壓縮的 AssetBundle 上調(diào)用 WWW.LoadFromCacheOrDownload 會生成相同數(shù)量的線程,這些線程隨后會與主線程競爭 CPU 時間。這很容易導(dǎo)致幀率卡頓。
因此,使用 WWW 來加載和解壓縮 AssetBundle 時,最佳做法是為創(chuàng)建的每個 WWW 對象的 threadPriority 設(shè)置適當?shù)闹怠?/p>

2. Application.backgroundLoadingPriority 說明

后臺加載線程的優(yōu)先級。
可用于控制異步加載數(shù)據(jù)所需的時間以及在后臺加載時對游戲的性能影響。

加載對象(Resources.LoadAsync、AssetBundle.LoadAssetAsync、AssetBundle.LoadAllAssetAsync)、場景 (SceneManager.LoadSceneAsync) 的異步加載函數(shù)在單獨的后臺加載線程中執(zhí)行數(shù)據(jù)讀取和反序列化,并在主線程中執(zhí)行對象集成。 “集成”取決于對象類型和紋理,網(wǎng)格意味著將數(shù)據(jù)上傳到 GPU,音頻剪輯可準備數(shù)據(jù)以進行播放。

為了防止卡頓,會限制主線程上執(zhí)行的時間:
- ThreadPriority.Low - 2ms;
- ThreadPriority.BelowNormal - 4ms;
- ThreadPriority.Normal - 10ms;
- ThreadPriority.High - 50ms.
這是所有異步操作在主線程的單個幀內(nèi)所能花費的最長時間。

using UnityEngine;
using System.Collections;

public class ExampleClass : MonoBehaviour 
{
    void Example() 
    {
        Application.backgroundLoadingPriority =  ThreadPriority.High;
        Application.backgroundLoadingPriority =  ThreadPriority.Low;
        
        // ----- 僅做演示使用 -----------
        WWW www = new WWW("");
        www.threadPriority =  ThreadPriority.BelowNormal;
        // -----  end ------------------
        
    }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。