概述
本文檔是為正在開始使用虛幻引擎進行開發的程序員提供的。它簡單地講解了基礎代碼的各個方面。它絕不是一個針對引擎的完整指南,而是一個在您編譯引擎代碼之后的一個很好的准備工作。如果您還沒有編譯您的項目,請訪問首先訪問: 入門指南或快速入門頁面。
目錄結構
當從Perforce上同步了UE3基礎代碼后,在您的Perforce depot(倉庫)的根文件夾中應該有一個稱為 UnrealEngine3 的目錄。
在"UnrealEngine3"文件夾內有以下目錄:
- Binaries - 這個文件中包含二進制對象。比如,編譯后的 引擎/游戲 版本、UE3所需要的DLL文件(Direct X、wx 運行時系統等)、編輯器資源文件(圖標圖像)。
- Development -這是引擎的源碼真正存在的地方,在這個文件夾中有:
- Build -這里存儲着用於啟動在我們的Continuous Integration Server(CIS)[連續集成服務器]上各種類型編譯的批處理文件。CIS可以為我們檢查編譯並盡可能地捕獲編譯錯誤。
- Documentation -存儲文檔文件的文件夾。我們自動生成的windows幫助文檔就存儲在這里(UnrealEngine3.chm)。這個幫助文檔是幫助您快速瀏覽Unreal源碼的很好的資源。
- External -所有不是Epic公司的庫源文件存儲在這個文件夾中。比如libPNG、 wxWidgets、zlib、Cg等。
- Intermediate -所有的中間編譯文件存儲在這里。.obj文件、預編譯頭文件等。
- Src -源碼文件和項目的makefiles。主要的UnrealEngine3解決方案存在於文件夾中。在這個解決方案中也包含了每個項目的文件夾。一個實例項目可以像這樣進行細分目錄:
- Game Folder(游戲文件夾)
- 在工程主文件夾中是工程的visual studio項目文件。
- Classes -保存.uc(UnrealScript)文件的文件夾。
- Inc -保存.h文件的文件夾。
- Src -保存.cpp文件的文件夾。
- Game Folder(游戲文件夾)
- Tools -保存各種引擎相關工具的所有源碼的文件夾, 比如UDE、vistual studio macros(vistual studio宏)及一些命令行工具。
- Engine/Game folders -在Binaries 和 Development文件夾之后是文件夾Engine,然后是使用這個引擎的每個游戲的文件夾。
- Config -包含着用於保存那個游戲設置的.ini文件。
- Content -包含那個游戲內容包的文件夾。
- Localization - 包含那個游戲的任何本地化文本的文件夾。
- Logs -包含着當運行那個游戲時產生的日志文件的文件夾。
- Script -包含着那個游戲編譯后的UnrealScript代碼(.u文件)。
工程結構
為了分離系統並幫助維持跨平台的兼容性,UE3被分割成了多個工程。
基本的結構如下所示(從最層代碼到高層層次代碼):
- Core
- Engine
- Editor
- UnrealED
注意,所有的這些工程都要建立於彼此之上的,這意味着Engine依賴Core、Editor依賴Engine、UnrealED依賴Editor。
- Core: Core是最低級別的類,它是指一些類似於字符串類、數組類、內存管理器等東西。這里是核心腳本和加載代碼所存在的地方。
- Engine: Engine文件夾是渲染和游戲性代碼存在的地方。同時包括了和actors、碰撞檢測以及很多其它的子系統。這里是大多數‘游戲界面’代碼所在的地方。
- Editor: Editor由僅當編輯器運行時使用的類和程序組成。這些類允許用戶操作多邊形、畫刷、地形及執行其它的通常在游戲中不能執行的動作。
- UnrealED: UnrealED是編輯器的真正UI實現,這是編輯器應用程序代碼存在的地方。目前我們使用wxWidgets作為我們的UI工具集。任何需要書寫的wxWidgets代碼都要放到UnrealED中。這里的觀念是'Editor'工程包含了所有編輯工具的功能性代碼,而UnrealED僅是那些功能的UI封裝。
也有很多針對其它平台的特定功能,比如D3DDrv(渲染的Direct 3D實現),WinDrv(創建視口、處理事件的Windows實現等)。如果一個工程是跨平台界面的特定平台實現,那么很可能它需要附加后綴Drv。
游戲/引擎 代碼
虛幻引擎一般把游戲代碼和引擎代碼分割為2個不同的程序語言:
- 引擎代碼:
- 使用C++語言書寫。
- 使用".h" 和".cpp"擴展名,並分別存儲在工程的"Inc" 和 "Src"文件夾中。
- 游戲代碼:
- 使用Unreal Engine的獨特語言:UnrealScript。這種語言在很多方面和Java類似。請參照UnrealScript 參考頁面獲得更多信息。
- 使用擴展名".uc",存儲在工程的"Classes"文件夾中。
- 在執行前進行編譯。
Unreal C++標准
- Unreal已經在整個引擎中定義了它自己的一組數據類型集合(
INT
、FLOAT
、UBOOL
等)。應該總是使用這些數據類型,而不是標准的C++數據類型,從而保證跨平台的兼容性。 - Unreal為字符串使用了寬字符(
TCHAR
)。所有的字符串文字都需要在TEXT()
宏進行封裝,從而確保它們可以正確地被轉換為寬字符。
示例:
const TCHAR* TestString = TEXT("My Test String");
關於虛幻編碼規范的更多信息,請參照編碼規范頁面。
對象命名規則
在類和struct前附加一個字母前綴是很重要的,因為Unreal使用這些前綴讓程序員知道應該如何處理一個對象。
- FClassName
- 實例: FString, FVector
- 應用: 任何帶有字符前綴‘F’的對象是標准的C++的struct(結構體)和類,這些對象沒有必須繼承其它任何特殊東西。
- TClassName
- 實例: TArray, TMap
- 應用: 任何帶有字符前綴‘T’的對象是模板類,這些對象沒有必須繼承其它任何特殊東西。
- UClassName
- AClassName
- 實例: AActor, ABrush, APointLight
- 應用: 任何帶有字符前綴‘A’的對象是從AActor繼承而來的類或struct(結構體)。AActor是基礎'Actor'類。Actors和一般的UObject是不同的,因為它們在游戲世界中由實際的位置和真實的項目。僅actors可以在網絡上進行復制以及使用UnrealScript狀態。Actors也可以繼承UObject,並且同樣地遵循應用到帶有U前綴的對象的不能刪除規則。
UnrealScript 文件
本文檔僅簡要地略微談到了一個新的程序員在使用虛幻引擎時需要處理的某些問題。
關於UnrealScript的全面描述,請參照UnrealScript參考指南頁面。
類的選項修飾符
當聲明類時,可以指定一些UnrealScript Classes的選項。關於這個功能的詳細介紹,請參照UnrealScript參考指南: UnrealScriptReference#Class_overview。
在本講解中,我們將簡要地覆蓋這些選項中的一個,因為它很容易使初識虛幻引擎的程序員犯錯誤。
使用 native 選項修飾符的自動生成頭文件
如果為一個類指定了 native
選項,那么UnrealScript編譯器將會自動地為那個UrealScript類生成相應的C++類聲明。這些頭文件具有后綴詞"Classes",一般和工程的名稱相關。比如"EngineClasses.h"、"EnginePhysicsClasses.h"、"EditorClasses.h"等。
因為當指定 native
時,UnrealScript將會自動生成C++類,所以程序員應該注意不要修改自動生成的頭文件,而是在.uc文件中進行修改。
noexport選項修飾符
某些類在指定了 native
的同時也指定了 noexport
選項。這些類不能自動生成相應的C++部分,但是仍然期望C++聲明存在。所以程序員必須自己書寫一個頭文件。在引擎中有很多這種情況的示例(請參照 Development/Src/Editor/Inc/Editor.h 文件中的UEditorEngine)。
noexport
UnrealScript 類需要和它們的C++對應部分保持‘同步’。因此,當修改UnrealScript文件時,程序員應該小心。
關於編譯native 類的更多信息,請參照編譯Native 類。
UObjects
因為UObjects是由引擎自動管理的,所以可能有一些新程序員不熟悉的獨特的微小差別:
- UOject永遠不要使用
new
進行創建, 而是用ConstructObject
模板函數。 - UOject永遠不要使用
delete
進行刪除。垃圾回收器將會自動地處理刪除UObjects。 UObject::StaticClass
可以用於獲得指向任何UObject靜態實例的指針。
AActor
Unreal World對象包含了它內部所有的Actors列表。
- 不能使用
new
或ConstructObject
來創建AActors – 您應該使用SpawnActor
函數。 - 要想銷毀一個Actor,請使用定義在UWorld中的
DestroyActor
函數。 - AActors可以包含一組UActorComponents。這些是提供較小的、正交單元的功能的有用對象。這可以使一個光源、粒子系統、聲效等。
序列化
虛幻引擎的一個強大功能是它可以對定義在.uc文件中的UObjects的所有屬性根據名稱自動地進行序列化。這允許您改變屬性的順序、添加新的屬性、在類層次中移動屬性,並且這些操作不會破壞向后的兼容性。
因為Unreal垃圾回收系統使用序列化來決定哪個 UObjects 是 可獲得的 ,所以您需要確保您具有到任何您不想清除的UObjects的序列化引用。在編輯器中創建工具時是可能導致問題的一種情況。我們一般從FSerializableObject接口繼承工具,它提供了一個=Serialize= 函數,可以通過實現這個函數來保存到在工具中創建的UObjects的引用。
void FSomeTool::Serialize(FArchive& Ar) { Ar << SomeUObjectPointer; }
如果您使用native序列化工具來序列化永久性數據,您需要明確地支持老版本的序列化數據。要想啟用這個功能,兩個版本號存儲在每個包中,一個供引擎使用,一個供授權用戶使用。當授權用戶在進行序列化改變時,可以更新 GPackageFileLicenseeVersion
,並且在反序列化過程中將會檢查 Ar.LicenseeVer()
來決定保存的是哪個版本的序列換數據。
配置系統
UE3使用層次化的配置系統,意味着默認值將會從 base(基類) 的配置文件向下傳遞,並且子類可以覆蓋這些基類的配置文件。
所有的配置文件都是.INI文件,並且遵循特殊的命名規則:
- 基類配置文件放置在 UnrealEngine3\Engine\Config文件夾中,文件名具有前綴單詞 Base 。
- 每個文件都有它自己的 Config 文件夾和一組.INI配置文件。這些文件的前綴是擁有它們的游戲的名稱。
比如,Editor配置文件的結構將是:
- Engine\Config\BaseEditor.ini
- "ExampleGame"的INI文件: ExampleGame\Config\DefaultEditor.ini
- "ExampleGame"的INI文件: ExampleGame\Config\ExampleGameEditor.ini
- "ExampleGame"的INI文件: ExampleGame\Config\DefaultEditor.ini
這個系統是強大的,因為它也用於為腳本中定義的屬性填充數據,而這些腳本屬性可以非常快速地配置游戲的任何部分。
主Tick(更新)循環
引擎的主Tick循環可以在LaunchEngineLoop.cpp文件中找到: FEngineLoop::Tick()
。這個函數調用UEngine類的 Tick
函數,這樣它將會更新游戲世界(UWorld)並監控更新引擎的其它各種子系統。
如果您想獲得關於Actor ticking(更新)循環函數是如何工作的,請參照Actor 更新頁面
結論
虛幻引擎編程乍一看令人畏懼,但是隨着時間的推移,您將會開始理解是某些復雜設計的決定使得它成為了今天的樣子。既然您已經學習了虛幻引擎編程的第一個速成教程,那么請隨便瀏覽UDN上提供給程序員的其它技術資源。
這里是為初學者提供的一些有用頁面:
虛幻引擎編碼規范:
編碼規范
如何使用ExampleGame 創建一個新的游戲項目:
ExampleGame指南
如何跟蹤ue3中您的內存應用情況:
Memory使用
actor更新循環是如何工作的:
Actor更新
UnrealScript參考指南(這是必讀頁面):
虛幻腳本概述:
關於編譯標記為'native'類的更多信息:
編譯Native類
虛幻引擎中常見的技術問題(FAQ):
常見技術問題
ClassificationForm | |
---|---|
Relevant topics | UnrealScriptTopics, GettingStartedTopics, TechnicalTopics |
Engine build | None/All |
Applicable platforms | |
Document availability | UE3Licensees |
Access required | |
Origin | CodeOrientation |
Revision | 1.11 |
Language | zh |