UE3代碼閱讀需知


     掌握一款龐大的引擎,要一下子掌握真的很難,慢慢地從Editor,Script,各個模塊細節,再到源碼,一步一個腳印必須扎實,還有,必須學會溫故而知新,有很多東西一開始一閱而過,以為簡單,實則不然,今天,就不想從最基本的CodeOrientation中學到了很多~

       下面就總結一下相關資料:

閱讀一款3D引擎的方法備忘

(轉自平民程序 - linghuye's blog

     要帶着引擎系統所共有的問題去閱讀,不要被具體引擎的實現思路牽着走,要思考這個引擎如何實現或繞過(如不考慮低端機)這些必然要面臨的問題.

首先,最重要的必須,在Debug模式下調試起來一個主場景程序,然后沿着代碼流走幾遍,在代碼里閑逛,生成第一印象,留意基礎工具設施類(如字符串內存管理),大約3小時.
然后帶着如下每一個問題(不分先后)去走流程,走邏輯,弄清引擎的業務處理方法.

1.SetStreamSource,SetIndices,DrawIndexedPrimitive的調用是在哪里(哪個cpp哪個類的哪個函數),整個工程有幾個DrawIndexedPrimitve,DrawPrimitveUp,DrawXXX,被統一管理了嗎,還是零零散散地分布在各個cpp各個類?

2.紋理資源是如何管理的,句柄,ID,指針, 按使用時間,按使用計數? 模型頂點資源是如何管理的,是否有Buffer分配上的優化(比如頂點緩沖整合)? 渲染的實例數據如何管理,如何與資源概念區分的? 純3D資源如Shader/RenderTarget是如何管理的?

3.場景管理是怎樣搭建的,如何包含區分節點實例數據和資源數據?鏡頭是如何被各模塊訪問的?剔除不可見物件的代碼行在哪里?兼容各種算法嗎,使用了具體的算法是什么?不論使用何種算法,場景管理模塊是否提供了清晰的需求定義接口?

4.骨骼動畫是在哪里計算的,具體到頂點乘以矩陣是在哪個cpp的哪個代碼行里?Socket實現在哪里?如果有高級動畫系統,骨架在哪里,有什么功能?動作融合的矩陣間過渡代碼在哪一行?

5.異步數據加載是怎樣做的,在哪個cpp里,由哪個模塊管理?各個資源的加載讀取cpp代碼行在哪里?

6.渲染管線如何為ShadowMap提供深度圖,如何為CubeMap,水面反射提供場景RenderTarget?如何管理固定流水線狀態RasterState的?

7.材質管理系統是如何運作的(通常都是technique + multipass),如何並入管線的,如何從理論上保證可以實現各式各樣的效果的?如何抽象兼容固定和可編程流水線的? 如果是抽象管理的,如何抽象掉不同的technique下的不同的數據?管線里是否有獨立的后期效果,還是用材質表達出來?材質是否可以腳本化?材質是要分組的,排序的代碼段在哪個cpp的哪里?

8.特效如粒子系統到最后是使用哪個DrawXXX畫出來的? 粒子系統是動態公式計算(不要理會具體公式)還是幀動畫?

9.界面2D Texture Draw是如何被支持的?文字渲染是如何被支持的,特別是如何支持中文的,字體資源如何被管理?是否使用Freetype,是否支持東亞文字?

10.物理系統的接口是如何定義引擎的需求的?或者就是亂糟糟地直接用上.


一個引擎的架構圖

不盡然相同,但可以很好地參照

http://blog.csdn.net/Jaredz/article/details/4411614):

框架圖

注:

UE中的RHI即是RenderHardwareInterface,由下面DX,OG等Driver做成實現;

UScript的架構不同於普通腳本,本身具有底層語言的特性,諸多的細節是為Editor做出的特殊化處理,實際上與Engine更類似於平行的關系,編譯運行,可與Native的C++層相互調用;

虛幻引擎3的代碼講解

轉自UDN:https://udn.epicgames.com/Three/CodeOrientationCH

概述


本文檔是為正在開始使用虛幻引擎進行開發的程序員提供的。它簡單地講解了基礎代碼的各個方面。它絕不是一個針對引擎的完整指南,而是一個在您編譯引擎代碼之后的一個很好的准備工作。如果您還沒有編譯您的項目,請訪問首先訪問: 入門指南快速入門頁面。

目錄結構


當從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文件的文件夾。
    • 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已經在整個引擎中定義了它自己的一組數據類型集合( INTFLOATUBOOL 等)。應該總是使用這些數據類型,而不是標准的C++數據類型,從而保證跨平台的兼容性。
  • Unreal為字符串使用了寬字符( TCHAR )。所有的字符串文字都需要在 TEXT() 宏進行封裝,從而確保它們可以正確地被轉換為寬字符。

示例:

const TCHAR* TestString = TEXT("My Test String");

關於虛幻編碼規范的更多信息,請參照編碼規范頁面。

對象命名規則

在類和struct前附加一個字母前綴是很重要的,因為Unreal使用這些前綴讓程序員知道應該如何處理一個對象。

  • FClassName
    • 實例: FString, FVector
    • 應用: 任何帶有字符前綴‘F’的對象是標准的C++的struct(結構體)和類,這些對象沒有必須繼承其它任何特殊東西。

  • TClassName
    • 實例: TArray, TMap
    • 應用: 任何帶有字符前綴‘T’的對象是模板類,這些對象沒有必須繼承其它任何特殊東西。

  • UClassName
    • 實例: UObject, UEngine, UGameEngine
    • 應用: 任何帶有字符前綴‘U’的對象是從UObject繼承而來的類或struct(結構體)。UObjects是特殊的,因為它們可以被引擎進行自動地垃圾回收。這意味着 UObject將永遠不能被刪除! 當沒有對它們的引用時,引擎將會自動地對它們進行垃圾回收。這同時也產生了另一個需要程序員處理的問題: 如何存儲到一個UObject的引用。我們通過序列化解決這個問題,關於序列化將稍后在本文檔進行討論。

  • 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列表。

  • 不能使用 newConstructObject 來創建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

這個系統是強大的,因為它也用於為腳本中定義的屬性填充數據,而這些腳本屬性可以非常快速地配置游戲的任何部分。

主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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM