天天看點

虛幻4随筆4 從工程開始



前文說到ue3開始,虛幻就使用了unrealbuildtool(以下簡稱ubt)來編譯和生成代碼。

為什麼這麼做而不是使用vs是很好了解的:因為vs跨平台會比較麻煩。像虛幻這樣體量的工程,單為工程做一次vs配置就基本是一天的時間

而且ue4還不像ue3那樣就十幾個工程,把所有uproject都看做工程的話,得幾十了。依賴關系複雜度幾何增長,用vs的工具去維護……而且要維護各個平台和配置……再加上維護完後mac、linux還得維護一遍……

但是為什麼不使用成熟的cmake呢,私以為可能是因為ubt裡有一系列錯綜複雜的規則,用cmake制作出來,即便可讀性ok,調試也比較麻煩。而且cmake對引擎使用者提出了一定的要求,而ubt則相對簡單——隻要你不糾結它如何實作。

官網的這篇文章詳細解釋了為什麼要做一個build tool出來:

what are the advantages of generating project files?

可以先看看ubt的基本規則:

目前說來,虛幻的所有代碼集中在下面幾個檔案夾裡:

<root>的source,這個檔案夾裡主要是引擎代碼。

其中:

source/runtime裡主要是引擎的核心代碼。

source/developer裡似乎主要是一些工具工程。

source/editor裡是編輯器相關代碼。

source/programs裡是引擎使用中需要用到的工具。比如ubt、unrealheadertool、swarm(分布式光照計算系統)等等。

source/thirdparty裡是各種第三方庫。

<root>的plugin,這個檔案夾裡有各式各樣的plugin實作。特殊的是plugin的組織中需要多一個uplugin,可能是plugin下可能會有一些資源什麼的吧。我們後面再來看uplugin。

<工程項目>的source,如果是代碼工程的話。

ubt目前隻認這幾個檔案夾,也就是說,如果你要為引擎擴充功能,您隻能在這些檔案夾裡建立自己的工程。這一點是在ubt裡寫死的,有代碼的可以關注一下ubt工程的findallrulessourcefiles這個方法。

在這些檔案夾裡,您可以搜尋到大量的*.build.cs檔案,這些build.cs就是虛幻的工程組織核心,基本上,每個build檔案都可以被視為一個工程檔案,而build檔案所在的檔案夾可以被視為此工程的根目錄。接下來,我們不妨稱這些擁有build.cs的檔案夾為工程。ubt一開始會先去找所有的build.cs,把它們放在一起生成一個臨時的dll。然後基于它們逐個進行一系列的代碼分析工作,最後調用指令行進行編譯和連接配接過程。

對于每個工程而言,代碼一般都散落在下面幾個檔案夾:

classes:如果你在工程根目錄下寫了個classes,就相當于告訴ubt這些檔案是要用unrealheadertool來生成運作時反射資訊的。是以,這個檔案夾裡頭檔案的寫法必須符合可反射類的寫法規範。

還記得虛幻的哪些類是可反射的嗎?對了,所有uobject的派生類包括aactor的派生類。具體是否有所驗證還沒看,不過最好是按照這個節奏來。

規範上無非主要就是ustruct、uclass這些宏,抄幾個就能找到感覺,或者用編輯器的類生成功能也可。

看起來,虛幻引擎釋出時(不是通過編譯生成,而是通過launcher下載下傳的那種),這些classes檔案是随引擎釋出的,友善不具備全代碼的mod愛好者和blueprint開發者們來制作遊戲。

public:公共頭檔案,跟classes一樣随着引擎釋出而釋出,是以這裡一般都是些比較開放的接口,比如子產品入口、功能核心接口什麼的。基本上這些接口沒有廢話,很清晰,跟實作相關的細節隐藏得非常好。與classes相同,如果你的工程裡有public,那麼裡面的.h就會被當作public來。

private:這個檔案夾似乎不是虛幻定死的,也就是似乎可以不用private的名字,或者多來幾個檔案夾什麼的。除了uht中有一段代碼與之有一定關聯之外,ubt裡是完全沒有跟這個有關的東西。它裡面基本上就是各種實作代碼,以及要在實作間共享的頭檔案。你也可以建立其他類似的檔案夾,隻需要build.cs裡寫上相應的檔案夾名即可:

虛幻4随筆4 從工程開始

此外還有需要注意的地方是source根目錄下的target.cs檔案,target的最終目标一般都是可執行檔案,可以說,target是整個生成期的入口,生成會首先從找到target開始,如果沒有target或者找不到,就會直接失敗。

此外,需要注意的是,target.cs裡面寫的類的類名,必須是target.cs的檔案名加target,例如:sample.target.cs,其類名必須是sampletarget。ubt的gettargettypeandrulesinstance方法裡印證了這一點。

ubt裡面還是有不少限定用法的,target就是其中之一,虛幻是一個比較強調命名的引擎,改名有很多麻煩,最好是能夠一步到位。

今天抽空看了看文檔,大概跟了跟ubt的流程,明天繼續。

繼續閱讀