藍圖編譯器概述(翻譯)


本文依據官方文檔翻譯而來,注意官方版本的文檔較舊(UE 4 4.9),新版本的類名已經改變。本文是直接翻譯而來,並沒有做相應改動。

藍圖,像常規的C++類一樣,需要編譯后才能在運行的時候使用。當你在藍圖編輯器中按下編譯按鈕時,那么編譯器就會把藍圖資源的屬性和圖轉換成類。

術語

FkismetCompilerContext

執行編譯工作的類。每一次編譯都會生成一個新的實例。存儲需要編譯類的引用,藍圖等。

FKismetFunctionContext

持有編譯一個函數的信息,比如相關圖的引用,屬性以及生成的UFunction。

FNodeHandlingFunctor

一個用來處理一類節點的幫助類。包含用於注冊引腳連接的函數,並且生成編譯語句。

FKismetCompiledStatement

編譯中的工作單元。編譯器會把節點轉換成一系列的語句,然后編譯器后端會把這些節點翻譯成字節碼操作。

例子:變量賦值、無條件跳轉(goto),調用(call)

FKismetTerm

圖中的一個末端(字面量、常量、或者變量引用)。每一個數據引用接連都會跟它們中的一個連接。為了抓取變量或者中間值等你也可以在NodeHandlingFunctor中來創建你自己的項。

編譯過程

編譯藍圖的一個基本過程如下圖所示:

*僅適用於完全編譯

清理類

類是就地編譯的,這意味着同一個UBlueprintGeneratedClass被清除並且會重復得使用,因此指向這個類的指針不必修正。CleanAndSanitizeClass()把屬性和函數從類中移動到一個臨時包中的垃圾類中,然后清除類中的所有數據。

創建類的屬性

編譯器遍歷藍圖的NewVariables數組以及其它地方(比如構建腳本等)來找到類需要的所有屬性,然后通過函數CreateClassVariablesFromBlueprint()在UClass內創建UProperties。

創建函數列表

編譯器通過處理事件圖表、常規函數圖表來創建函數列表,並且預編譯這些函數。例如為每一個上下文調用PrecompileFunction()函數。

處理事件圖表

事件圖表的處理通過調用CreateAndProcessUberGraph()函數而進行。它把所有的事件圖表拷貝到一個大的圖表中去,這之后節點會被展開。然后為圖表中的每一個事件節點創建一個函數的存根(stub),並且第一個事件節點都會生成一個對應 的FKismetFunctionContext。

處理函數圖表

處理常規函數圖表的過程是通過調用ProcessOneFunctionGraph()函數來完成的,它會復制每一個圖表到一個臨時的圖表里面,在這個圖表里節點被會展開。每一個函數圖表都會創建一個FKismetFunctionContext。

預編譯函數

函數的預編譯是通過調用每一個上下文中的PrecompileFunction()。這個函數會做以下幾步的操作:

  1. 安排執行並且計算數據依賴。
  2. 去除那此沒有使用的或者不是一個數據依賴的節點。
  3. 在每一個存在的節點上運行RegisterNets()節點處理器。
  4. 為函數中的值創建FKismetTerms。
  5. 創建UFunction和相關的屬性。

綁定和鏈接類

現在編譯器已經知道類的所有UFunction和UProperty了,現在它可以調用綁定和鏈接類了,這個過程包括創建屬性鏈,設置屬性大小,函數映射等。在這個時候,它實際上只有一個類頭,不包含最終的標記和元數據,也沒有一個類默認對象(CDO)。

編譯函數

接下來需要為剩下的節點生成FKismetCompiledState對象,通過節點處理器的Compile()函數調用AppendStatementForNode()完成。這個函數會為當前編譯的函數創建FKismetTerm對象只要它們只用來局部使用。

完成編譯類

為了完成編譯這個類,在通過一些最終檢查來確保所有事情都做好之前,編譯器會定下來類的標記並且從父類繼承標記和元數據。

后端發出生成的代碼

后端把每個函數上下文中的語句集合轉換成代碼。有兩個可以使用的后端。

  1. FKismetCompilerVMBackend 把FKCS轉換成UnrealScript 虛擬機的字節碼,然后就把這些字節碼序列化到函數的腳本數組中。
  2. FKismetCppBackend 產生用於調試的像C++的代碼。

拷貝類默認對象屬性

使用一個特別的函數CopyPropertiesForUnrelatedObjects(),編譯器會把類原來的CDO中的值拷貝到新的CDO。屬性通過標記的序列化拷貝,因此只要名字一致,它們應該會被正確的轉移。CDO的組件會被重新實際化並且在這個階段修正。這個生成類的CDO是權威的(authoritative)。

重新實際化

由於類可能會改變了大小 或者屬性被添加或移除,編譯器需要重新實例化剛編譯的類的所有對應。這個過程使用TObjectIterator來找到這個類的所有實例,生成一個新的然后使用CopyPropertitiesForUnrelatedObjects()函數來把舊的實例拷貝到新的實例里面去。

要想了解更多的細節,查看FBlueprintCompileReinstancer類。


免責聲明!

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



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