簡(jiǎn)單的手機(jī)網(wǎng)站模板下載國(guó)內(nèi)企業(yè)網(wǎng)站模板
Unity的實(shí)體組件系統(tǒng)(ECS)是支撐DOTS模塊和技術(shù)的面向數(shù)據(jù)架構(gòu)。ECS為Unity中的內(nèi)存數(shù)據(jù)和runtime進(jìn)程調(diào)度提供了高度的控制和確定性。
ECS for Unity 2022 LTS 配備了兩個(gè)兼容的物理引擎,一個(gè)高級(jí)的Netcode package,以及一個(gè)用來(lái)將大量ECS數(shù)據(jù)渲染到Unity的可編程渲染管線(SRP)、通用渲染管線(URP)和高清晰度渲染管線(HDRP)的渲染框架。這套ECS框架與GameObject數(shù)據(jù)兼容,允許你使用一些Unity 2022 LTS中尚未原生支持ECS的系統(tǒng),如動(dòng)畫、導(dǎo)航、輸入或地形。
本節(jié)重點(diǎn)介紹DOTS的功能,以及它們?nèi)绾螏椭_發(fā)者避免前面提到的會(huì)造成CPU性能瓶頸的代碼。
學(xué)習(xí)有關(guān)DOTS具體內(nèi)容的最佳起點(diǎn)是EntityComponentSystemSamples Github,它包含了說(shuō)明書和視頻的同時(shí)還包含許多示例工程。
然而,在深入學(xué)習(xí)這些示例之前,我們先來(lái)看看用于構(gòu)建這套技術(shù)棧的功能和模塊。
C#job系統(tǒng)
C#job系統(tǒng)提供了一種簡(jiǎn)單高效的方式來(lái)編寫多線程代碼,幫助你的應(yīng)用充分利用所有可用的CPU核心。
與DOTS的其他功能不同,job系統(tǒng)不是一個(gè)單獨(dú)的模塊,而是包含在Unity核心模塊中。
因?yàn)镸onoBehaviour的更新只在主線程上執(zhí)行,所以許多Unity游戲最終都會(huì)把所有游戲邏輯都運(yùn)行在一個(gè)CPU核心上。為了利用額外的核心,你可以手動(dòng)創(chuàng)建和管理額外的線程,但這樣做在提高代碼難度的同時(shí)又提高了代碼風(fēng)險(xiǎn)。
作為一種更簡(jiǎn)單的替代方案,Unity提供了C#job系統(tǒng):
— job系統(tǒng)維護(hù)一個(gè)job線程池,每個(gè)目標(biāo)平臺(tái)的額外核心對(duì)應(yīng)一個(gè)線程。例如,當(dāng)Unity在八個(gè)核心上運(yùn)行時(shí),它會(huì)創(chuàng)建一個(gè)主線程和七個(gè)job線程。
— job線程執(zhí)行稱為job的工作單元。當(dāng)job線程空閑時(shí),它會(huì)從job隊(duì)列中拉取下一個(gè)可用的job進(jìn)行執(zhí)行。
— 一旦某個(gè)job開始在job線程上執(zhí)行,它就會(huì)一直執(zhí)行到完成(換句話說(shuō),job不會(huì)被搶占)。
job的調(diào)度和完成
— job只能被主線程調(diào)度(即,添加到j(luò)ob隊(duì)列中),不能從其他job中被調(diào)度。
— 當(dāng)主線程調(diào)用已調(diào)度job的Complete()方法時(shí),它會(huì)等待job完成執(zhí)行(如果job尚未完成)。
— 只有主線程可以調(diào)用Complete()。
— Complete()返回后,你可以確定job使用的數(shù)據(jù)在主線程上可以再次安全訪問,并且可以安全地傳遞給后續(xù)的被調(diào)度的job。
job安全性檢查和依賴關(guān)系
在多線程編程中,確保線程安全和管理線程之間的依賴關(guān)系對(duì)于避免競(jìng)態(tài)條件、數(shù)據(jù)損壞和其他并發(fā)問題至關(guān)重要。解釋這些陷阱超出了本指南的范圍。關(guān)鍵的要點(diǎn)是理解job系統(tǒng)如何處理安全性檢查和依賴關(guān)系:
— 為了確保隔離性,每個(gè)job都有自己的私有數(shù)據(jù),主線程和其他job無(wú)法訪問這些數(shù)據(jù)。
— 然而,job也可能需要與彼此或主線程共享數(shù)據(jù)。 共享相同數(shù)據(jù)的job不應(yīng)并發(fā)執(zhí)行,因?yàn)檫@會(huì)導(dǎo)致競(jìng)態(tài)條件。因此,當(dāng)你調(diào)度可能互相沖突的job時(shí),job系統(tǒng)的“安全檢查”會(huì)拋出錯(cuò)誤。
— 在調(diào)度job時(shí),你可以聲明它依賴于之前調(diào)度的job。 job線程在執(zhí)行某個(gè)job前會(huì)保證它依賴的所有的job都執(zhí)行完成,這樣你就可以安全地調(diào)度本來(lái)可能會(huì)沖突的job。例如,如果jobA和jobB都訪問相同的數(shù)組,你可以讓jobB依賴于jobA。 這確保jobB不會(huì)在jobA完成之前執(zhí)行,從而避免任何可能的沖突。
— 完成一個(gè)job時(shí),代表已經(jīng)完成了它直接或間接依賴的所有job。
許多Unity功能內(nèi)部都在使用job系統(tǒng),因此在Profiler中,你會(huì)看到不僅僅是你自己調(diào)度的job在job線程上運(yùn)行。
注意,job僅用于處理內(nèi)存中的數(shù)據(jù),而不是執(zhí)行I/O(輸入輸出)操作,例如讀取和寫入文件或通過(guò)網(wǎng)絡(luò)連接發(fā)送和接收數(shù)據(jù)。因?yàn)橐恍㊣/O操作可能會(huì)阻塞調(diào)用線程,在job中執(zhí)行它們會(huì)違背最大化CPU核心利用率的目標(biāo)。如果你想做多線程的I/O job,你應(yīng)該從主線程調(diào)用異步API或使用傳統(tǒng)的C#多線程。