《Inside UE4》-1-基礎概念
InsideUE4
創建測試項目
接上文的准備工作,雙擊生成的UE4Editor.exe,選擇創建測試C++空項目Hello(以后的源碼分析都會基於該最簡單的項目)
項目文件結構
VS項目和文件目錄:
可以看到,Config目錄里帶着3個最主要的配置,Editor,Engine,Game。代碼方面自動生成了用於編譯系統的3個.cs文件,C++代碼方面生成了一個Hello "Game Module",和HelloGameMode。
文件目錄:
- Binaries:存放編譯生成的結果二進制文件。該目錄可以gitignore,反正每次都會生成。
- Config:配置文件。
- Content:平常最常用到,所有的資源和藍圖等都放在該目錄里。
- DerivedDataCache:“DDC”,存儲着引擎針對平台特化后的資源版本。比如同一個圖片,針對不同的平台有不同的適合格式,這個時候就可以在不動原始的uasset的基礎上,比較輕易的再生成不同格式資源版本。gitignore。
- Intermediate:中間文件(gitignore),存放着一些臨時生成的文件。有:
- Build的中間文件,.obj和預編譯頭等
- UHT預處理生成的.generated.h/.cpp文件
- VS.vcxproj項目文件,可通過.uproject文件生成編譯生成的Shader文件。
- AssetRegistryCache:Asset Registry系統的緩存文件,Asset Registry可以簡單理解為一個索引了所有uasset資源頭信息的注冊表。CachedAssetRegistry.bin文件也是如此。
- Saved:存儲自動保存文件,其他配置文件,日志文件,引擎崩潰日志,硬件信息,烘培信息數據等。gitignore
- Source:代碼文件。
編譯類型
很多人在使用UE4的時候,往往只是依照默認的DevelopmentEditor,但實際上編譯選項是非常重要的。
UE4本身包含網絡模式和編輯器,這意味着你的工程在部署的時候將包含Server和Client,而在開發的時候,也將有Editor和Stand-alone之分;同時你也可以單獨選擇是否為Engine和Game生成調試信息,接着你還可以選擇是否在游戲里內嵌控制台等。
依照官方介紹
每種編譯配置包含兩種關鍵字。第一種表明了引擎以及游戲項目的狀態。第二個關鍵字表明正在編譯的目標。
狀態 | Engine | Game | 其他 |
---|---|---|---|
Debug (調試) | Debug | Debug | 必須在編輯器上加-debug參數才能反射查看代碼更改 |
DebugGame (調試游戲) | Release | Debug | 適合只調試游戲代碼 |
Development (開發) | Release | Release | 允許編輯器反射查看代碼更改 |
Shipping (發行) | Release | Release | 無控制台命令,統計數據和性能分析 |
Test (測試) | Release | Release | 啟用了一些控制台命令,統計數據和性能分析 |
目標 | 描述 |
---|---|
[empty] (空白) | 不帶編輯器的一個獨立可執行版本,需要提前打包烘培內容資源 |
Editor (編輯器) | 直接在編輯器里打開游戲項目 |
Client (客戶端) | 多人聯機項目,生成客戶端版本,需要提供 <Game>Client.Target.cs 文件 |
Server (服務器) | 多人聯機項目,生成服務器版本,需要提供 <Game>Server.Target.cs 文件 |
組合的各種情況:
Debug | DebugGame | Development | Shipping | Test | |
---|---|---|---|---|---|
[empty] | ✓ | ✓ | ✓ | ✓ | ✓ |
Editor | ✓ | ✓ | ✓ | ||
Client | ✓ | ✓ | ✓ | ✓ | ✓ |
Server | ✓ | ✓ | ✓ | ✓ | ✓ |
所以為了我們的調試代碼方便,我們選擇DebugEditor來加載游戲項目,當需要最簡化流程的時候用Debug來運行獨立版本。
命名約定
客觀來說,相比其他引擎的源碼,UE4的源碼還是非常清晰的,模塊組織也比較明了。但閱讀源碼的學習曲線依然陡峭,我想有以下原因:
1. UE4包含的模塊眾多,攏共有幾十個模塊,雖然采用了Module架構來解耦,但難免還是要有依賴交叉的地方,在閱讀的時候就很難理清各部分的關系。
2. UE4的功能優秀,作為業界頂尖的成熟游戲引擎,在一些具體的模塊內部實現上就脫離了簡單粗暴,而是采用了各種設計模式和權衡。同時也需要閱讀的人有相關的業務知識。比如材質編輯器編譯生成Shader的過程就需要讀者擁有至少差不多的圖形學知識。
3. 被魔改后的C++,UE4為了各平台的編譯和其他考量(具體以后說到編譯系統的時候再細討論),對標准的C++和編譯,進行了相當程度的改造,在UHT代碼生成和各種宏的嵌套之后,讀者就很難一下子看清背后的各種的機制了。
但萬丈高樓平地起,咱們也可以從最簡單的一步步開始學起,直到了解掌握整個引擎的內部結構。
在閱讀代碼之前,就必須去了解一下UE4的命名約定,具體的自己去查看官網文檔,下面是一些基本需要知道的:
- 模版類以T作為前綴,比如TArray,TMap,TSet
- UObject派生類都以U前綴
- AActor派生類都以A前綴
- SWidget派生類都以S前綴
- 抽象接口以I前綴
- 枚舉以E開頭
- bool變量以b前綴,如bPendingDestruction
- 其他的大部分以F開頭,如FString,FName
- typedef的以原型名前綴為准,如typedef TArray FArrayOfMyTypes;
- 在編輯器里和C#里,類型名是去掉前綴過的
- UHT在工作的時候需要你提供正確的前綴,所以雖然說是約定,但你也得必須遵守。(編譯系統怎么用到那些前綴,后續再討論)
基礎概念
和其他的3D引擎一樣,UE4也有其特有的描述游戲世界的概念。在UE4中,幾乎所有的對象都繼承於UObject(跟Java,C#一樣),UObject為它們提供了基礎的垃圾回收,反射,元數據,序列化等,相應的,就有各種"UClass"的派生們定義了屬性和行為的數據。
跟Unity(GameObject-Component)有些像的是,UE4也采用了組件式的架構,但細品起來卻又有些不一樣。在UE中,3D世界是由Actors構建起來的,而Actor又擁有各種Component,之后又有各種Controller可以控制Actor(Pawn)的行為。Unity中的Prefab,在UE4中變成了BlueprintClass,其實Class的概念確實更加貼近C++的底層一些。
Unity中,你可以為一個GameObject添加一個ScriptComponent,然后繼承MonoBehaviour來編寫游戲邏輯。在UE4中,你也可以為一個Actor添加一個藍圖或者C++ Component,然后實現它來直接組織邏輯。
UE4也支持各種插件。
其他的下篇再一一細說。
編譯系統
UE4支持眾多平台,包括Windows,IOS,Android等,因此UE4為了方便你配置各個平台的參數和編譯選項,簡化編譯流程,UE4實現了自己的一套編譯系統,否則我們就得接受各個平台再單獨配置一套項目之苦了。
這套工具的編譯流程結果,簡單來說,就是你在VS里的運行,背后會運行UE4的一些命令行工具來完成編譯,其他最重要的兩個組件:
UnrealBuildTool(UBT,C#):UE4的自定義工具,來編譯UE4的逐個模塊並處理依賴等。我們編寫的Target.cs,Build.cs都是為這個工具服務的。
UnrealHeaderTool (UHT,C++):UE4的C++代碼解析生成工具,我們在代碼里寫的那些宏UCLASS等和#include "*.generated.h"都為UHT提供了信息來生成相應的C++反射代碼。
一般來說,UBT會先調用UHT會先負責解析一遍C++代碼,生成相應其他代碼。然后開始調用平台特定的編譯工具(VisualStudio,LLVM)來編譯各個模塊。最后啟動Editor或者是Game.
更細的留待“編譯系統”再細細討論
引用
UE4深入學習QQ群: 456247757