.NET和Unity的未來,讓用戶編寫高性能代碼,并帶來長期的穩(wěn)定性與兼容性

來源:Unity官方平臺(tái)
作者:Unity官方平臺(tái)
時(shí)間:2022-06-21
3018
.NET生態(tài)正在多方面上積極動(dòng)態(tài)地演變,Unity希望盡快將這些改進(jìn)帶給廣大用戶。

.NET生態(tài)正在多方面上積極動(dòng)態(tài)地演變,Unity希望盡快將這些改進(jìn)帶給廣大用戶。Unity內(nèi)部的.NET技術(shù)小組正致力于不斷改進(jìn).NET集成,更新最新的C#特性與.NET Standard 2.1。但根據(jù)大家的反饋,Unity最近又在全面改善開發(fā)者體驗(yàn)上投入了更多力量。

640.jpg

.NET和Unity的演變

Unity與.NET的故事要從17年前說起,當(dāng)時(shí)的CTO決定開始采用Mono.NET運(yùn)行時(shí)和C#。Unity之所以偏愛C#,不僅是因?yàn)樗芎唵危€因?yàn)镴IT(just-in-time)編譯器可以將C#代碼轉(zhuǎn)譯成效率較高的原生代碼。而為了做到性能平衡、可控,Unity引擎剩下的大部分都采用了C++開發(fā)。

多年來,Unity一直依靠著Mono.NET運(yùn)行時(shí)和C#語言(2.0)的一個(gè)特定分支來運(yùn)行。在這期間,引擎對(duì)其他平臺(tái)的支持也在不斷擴(kuò)增。我們還開發(fā)了自己的編譯器和運(yùn)行時(shí):IL2CPP,讓你能夠針對(duì)iOS及部分主機(jī)平臺(tái)進(jìn)行開發(fā)。

與此同時(shí),整個(gè)微軟.NET生態(tài)系統(tǒng)也在不斷發(fā)展,并推出了新的許可和對(duì)非Windows平臺(tái)的支持。我們借著這股東風(fēng)在2018年升級(jí)到了Unity.NET Mono Runtime,并引入了更現(xiàn)代的C#版本(7.0以上)。同年,我們還發(fā)布了Burst編譯器的首個(gè)版本,開創(chuàng)了為C#分支快速生成原生代碼的先河。在取得這一突破后,Unity提出了一個(gè)新設(shè)想:將C#拓展到引擎剩余幾個(gè)關(guān)鍵部分、不再用C++進(jìn)行開發(fā),并為DOTS運(yùn)行時(shí)的開發(fā)做鋪墊。

Unity 2020 LTS和Unity 2021 LTS使用了新版C#語言和.NET API(如Span)。同時(shí),我們也看到.NET生態(tài)的性能有了極大的改善,其引入的csproj SDK風(fēng)格和蓬勃發(fā)展的NuGet生態(tài)正在讓開發(fā)環(huán)境變得更加友好。

我們將要做的事

經(jīng)過長時(shí)間的發(fā)展,Unity已經(jīng)包含了一個(gè)巨大的C++代碼庫,它繼承了Mono.NET Runtime的職能來直接與.NET對(duì)象互動(dòng)。這些代碼對(duì).NET(Core)Runtime來說不再合規(guī)或高效。

此外,Unity編輯器還綁定著一條復(fù)雜的自定義編譯管線,它不依靠MSBuild運(yùn)行,因此也不能輕易從引擎特性中獲益。

在過去幾年里,我們也一直在積極與廣大用戶交流,以發(fā)掘出真正能促使用戶成功的改進(jìn)。我們聽到大家非常想使用最新的C#語言、.NET運(yùn)行時(shí)技術(shù)和NuGet的第三方C#代碼。在談到Unity平臺(tái)的使用時(shí),大家都說希望借助高質(zhì)量的C#測試、調(diào)試和剖析工具,標(biāo)準(zhǔn).NET API和Unity API的優(yōu)秀整合,來最大限度地挖掘出硬件的性能。作為一名Unity C#程序員,一定希望Unity工具能夠與工具箱中的其他工具無縫銜接,能實(shí)現(xiàn)快速迭代,從而實(shí)現(xiàn)一流的運(yùn)行時(shí)性能。

要達(dá)到這個(gè)目標(biāo),我們得花幾年時(shí)間。

我們的做法

這項(xiàng)計(jì)劃的第一步是在Unity內(nèi)部集結(jié)所有熱衷于C#和.NET的員工,建立一支C#/.NET技術(shù)小組來開展工作。

我們的工作將建立在.NET生態(tài)系統(tǒng)之上,而非開發(fā)定制解決方案。為了讓用戶能享受新版.NET SDK/Runtime和MSBuild所帶來的性能與生產(chǎn)力提高,我們將從Mono.NET Runtime轉(zhuǎn)移到CoreCLR,即現(xiàn)代的.NET(Core)Runtime。

這項(xiàng)行動(dòng)也會(huì)帶來當(dāng)前.NET領(lǐng)域以外的創(chuàng)新,讓C#腳本能更快地完成.NET迭代。我們將致力于結(jié)合IL2CPP和Burst這兩個(gè)JIT和AOT(ahead-of-time)解決方案,在編譯效率和CodeGen(代碼生成)質(zhì)量之間的達(dá)到最佳平衡。

在外部,我們將與微軟、JetBrains等業(yè)內(nèi)伙伴合作,保證Unity創(chuàng)作者能用上最新的.NET技術(shù)。我們也在進(jìn)一步深入?yún)⑴c開源社區(qū)。這項(xiàng)工作將分成幾個(gè)步驟進(jìn)行。再來看看我們未來的計(jì)劃。

2022年的工作內(nèi)容

今年,我們的團(tuán)隊(duì)計(jì)劃在以下幾個(gè)方面開展工作。

640 (1).jpg

C#開發(fā)流程

迭代時(shí)間仍然是我們首要的工作重點(diǎn),我們清楚每一名用戶都想盡可能地利用起自己的時(shí)間。以下是我們改進(jìn)工作的幾個(gè)例子。

我們正在改進(jìn)編譯管線的IL Post Processing所耗費(fèi)的時(shí)間,它負(fù)責(zé)在C#被編譯后修改編譯好的.NET程序集?,F(xiàn)在IL Post Processing將在編譯階段后持續(xù)運(yùn)行,來降低約幾百毫秒的耗時(shí)。

隨著Burst編譯器的使用愈加頻繁,我們將采用一種可傳遞哈希算法來改進(jìn)代碼改動(dòng)檢測的精細(xì)度。如此一來,我們就能夠找出那些需要快速編譯的可爆發(fā)(Burstable)代碼。我們正在將Burst編譯器移出進(jìn)程,使其能在單獨(dú)的.NET 6.0可執(zhí)行程序中運(yùn)行,更快地完成代碼編譯。

我們還將改進(jìn)引擎每次調(diào)用TypeCache、在后臺(tái)建立鏡像數(shù)據(jù)(reflection data)的過程,借此改進(jìn)域的重新加載。

我們還將添加測試和驗(yàn)證流程來更好地跟蹤軟件包和項(xiàng)目模板的迭代時(shí)間倒退。

至于轉(zhuǎn)移到MSBuild,我們第一步須將編譯管線與Unity編輯器分割開來,并將其轉(zhuǎn)移到一個(gè)單獨(dú)的進(jìn)程中。這個(gè)過程涉及多年以來遺留下來的成千上萬行C++和C#代碼,我們要實(shí)現(xiàn)這一目標(biāo)就必須解開這些代碼——同時(shí)還要保持向下兼容。這項(xiàng)工作并不會(huì)在用戶的角度帶來多大變化,但它將鋪好通往MSBuild的道路并簡化引擎的維護(hù)。

我們還將改進(jìn)Burst的C#IDE調(diào)試體驗(yàn),推出一種新的調(diào)試模式,當(dāng)用戶在Burst代碼路徑上設(shè)置斷點(diǎn)時(shí),自動(dòng)將調(diào)試器切換到托管調(diào)試。這意味著你不必再手動(dòng)刪去調(diào)試路徑上的[BurstCompile]屬性。

現(xiàn)代化.NET運(yùn)行時(shí)

轉(zhuǎn)移至.NET CoreCLR運(yùn)行時(shí)的工作已經(jīng)開始,這是一個(gè)非常具有挑戰(zhàn)性的旅程。為了使整個(gè)過程能夠順利完成,我們將分步驟解決各個(gè)問題,并在保證現(xiàn)有Unity項(xiàng)目穩(wěn)定的前提下碎片化發(fā)布更新。

因此,整個(gè)遷移過程將分多個(gè)階段完成:

首先,我們將為桌面平臺(tái)上的獨(dú)立運(yùn)行版提供.NET CoreCLR的支持。該運(yùn)行時(shí)將和現(xiàn)有的Mono與IL2CPP后端一起在運(yùn)行版設(shè)置中列出。第一階段我們將完成Unity引擎核心部分(比編輯器部分小得多)的遷移,并盡量解決遷移過程所涉及的絕大部分技術(shù)挑戰(zhàn)。我們的目標(biāo)是在2023年期間發(fā)布這個(gè)新運(yùn)行時(shí),目前你仍需用.NET Standard 2.1 API訪問.NET運(yùn)行時(shí)。

然后,我們會(huì)把Unity編輯器移植到.NET CoreCLR,同時(shí)移除對(duì).NET Mono運(yùn)行時(shí)的支持。第二階段我們將挑戰(zhàn)不使用AppDomains在編輯器內(nèi)重新加載腳本,并完成向.NET CoreCLR轉(zhuǎn)移。這一階段也將涉及到升級(jí)IL2CPP、支持dotnet/runtime倉庫的基礎(chǔ)類庫。你將能使用完整的.NET 7.x或8.0 API。我們希望能在2024年里發(fā)布這個(gè)新的編輯器。

現(xiàn)代化Unity運(yùn)行時(shí)

Unity 2021 LTS新支持的.NET Standard 2.1使我們能夠從多個(gè)方面著手現(xiàn)代化Unity運(yùn)行時(shí)。我們目前正在推進(jìn)兩項(xiàng)改進(jìn)工作。

改進(jìn)async/await編程模型。基礎(chǔ)性的async/await編程方法主要用于編寫必須異步完成、不阻塞引擎主循環(huán)的游戲代碼。

2011年,在async/await成為.NET的主流之前,Unity引入了基于迭代器的異步運(yùn)算協(xié)程(coroutines),但這種方法并不兼容async/await,并且效率也更低。同時(shí),.NET Standard 2.1一直在改進(jìn)C#和.NET對(duì)async/await的支持,推出了ValueTask來更高效地完成async/await的運(yùn)算,并允許用戶自行用AsyncMethodBuilder編寫的類任務(wù)系統(tǒng)。

在有了這些改進(jìn)之后,我們將努力結(jié)合async/await與Unity中現(xiàn)有的異步操作(如等待下一幀或等待UnityWebRequest的完成)。第一步,我們將引入取消令牌(cancellation token),改進(jìn)MonoBehavior被銷毀時(shí)或退出運(yùn)行模式時(shí)被掛起異步任務(wù)的取消操作。我們也一直在與UniTask作者等社區(qū)貢獻(xiàn)者密切合作,保證他們能夠用上這些新功能。

利用Span減少內(nèi)存分配和拷貝。Unity本身是一個(gè)帶有C#編程外殼的C++引擎,兩種語言之間存在著大量的數(shù)據(jù)交換。這就造成引擎經(jīng)常性地來回復(fù)制數(shù)據(jù)、分配托管對(duì)象,造成工作效率低下。

C#7.2引入的Span可以有效改善這個(gè)問題,且.NET Standard 2.1默認(rèn)可使用Span值類型。近年來,你可能聽說過或讀到過許多歸功于Span的.NET運(yùn)行時(shí)重大性能改進(jìn)。我們同樣希望在Unity中利用起它,并有效地減少分配,從而減少Garbage Collection卡頓、提高大量API的整體性能。

立即登錄,閱讀全文
原文鏈接:點(diǎn)擊前往 >
文章來源:Unity官方平臺(tái)
版權(quán)說明:本文內(nèi)容來自于Unity官方平臺(tái),本站不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。文章內(nèi)容系作者個(gè)人觀點(diǎn),不代表快出海對(duì)觀點(diǎn)贊同或支持。如有侵權(quán),請(qǐng)聯(lián)系管理員(zzx@kchuhai.com)刪除!
掃碼關(guān)注
獲取更多出海資訊的相關(guān)信息
優(yōu)質(zhì)服務(wù)商推薦
更多
掃碼登錄
打開掃一掃, 關(guān)注公眾號(hào)后即可登錄/注冊(cè)
加載中
二維碼已失效 請(qǐng)重試
刷新
賬號(hào)登錄/注冊(cè)
小程序
快出海小程序
公眾號(hào)
快出海公眾號(hào)
商務(wù)合作
商務(wù)合作
投稿采訪
投稿采訪
出海管家
出海管家