UE4 Modules 和 PCH



本文參考:

https://zhuanlan.zhihu.com/p/107270501

https://docs.google.com/presentation/d/1rSFFQk7RxNAHevROfVvUNviUfIntLkO_HpdvzHLkNEs/view#slide=id.g6e0e4b3bcf_2_326

UE4模塊的加載方式

待補充

Modules

模塊是什么?一堆dll 類的集合,UE4被分為了1000個模塊

有什么作用?組織代碼,可移植性復用性,可以獲得更快的編譯和鏈接性能,也可以確認模塊何時加載

如何做一個Module? B U I L D

Build

Build,建立一個固定的目錄

[YourModuleName].Build.cs文件的作用用

描述如何編譯模塊、模塊的依賴等等

模塊的編譯只取決於.Target.cs和.Build.cs而不取決於sln

一個最少代碼的模塊包括:

和模塊名相同的C#類

構造函數中處理模塊的依賴性,必須依賴Core,里面包括了很多模塊相關代碼

Use

use 使用模塊

模塊的代碼並不是默認對其他的模塊暴露的

你需要隊每個函數或者類進行顯式的指定他是否導出

如果你不打算暴露任何代碼到模塊外,你可以不用分private和public的文件夾

這些代碼在藍圖中可以訪問,但是在其他模塊中不能使用

通過給UCLASS添加MinimalAPI(最小)標識來表示將其顯式導出到可以被其他模塊使用

要將某個函數暴露給其他模塊使用必須在函數前添加[YourModuleName]_API,全部大寫字母

要將整個類暴露就在類前加[YourModuleName]_API,全部大寫字母,這樣整個類的public部分都會暴露

由於這個類依賴了Actor類,所以我們在模塊的編譯時候會報錯

要用的話,就需要添加頭文件、添加模塊依賴關系

這里在publicDependency進行一個添加,因為其他的模塊要是引用這個NickNameActor他自然也會需要對Actor有依賴

關於private 和 public dependency的問題:

當這個關系只有一層時沒有任何區別

當涉及到三個模塊時,這里的依賴的public private就會起作用

頭文件內容傳遞,表示這個模塊可以調用其他模塊全部定義在在頭文件中的內容,如果有內容是 .cpp中定義,則會有無法解析的外部符號錯誤(就是將頭文件一起編譯,但是不會做鏈接,對應IncludePathModuleNames,現在基本已經棄用了)

把定義寫在頭文件中意味着他可能會被多次編譯,將拖慢編譯速度

DependencyModuleNames,則是將兩個模塊鏈接,則表示這個模塊可以調用到.cpp中定義的內容

private會切斷頭文件路徑鏈接的傳遞,你的模塊被其他的模塊依賴時這些引入的頭的鏈接都不會傳遞

非常重要的依賴傳遞圖

img

當你的模塊被其他的模塊引用的時候,情況很多,上圖基本包括了所有情況

你private 引用了別的module,引用了你module的module嘗試找你的子模塊的代碼的時候就會出現文件找不到的錯誤

總結選擇:建議使用private鏈接,他們會減少編譯時間!

Implement

Implement,實現模塊

#include "Modules/ModuleManager.h" // which is in core module


IMPLEMENT_MODULE(FPlatformCommonModule, PlatformCommon)

這句話可以在你的模塊的任何地方寫,這句調用就是將你的模塊的主類給暴露給引擎

實現這個模塊的類必須繼承這個IModuleInterface的接口,一般來說做個空類就好了可以使用UE自帶FDefaultModuleImpl類

有關module的接口有很多,最基本的就加載和卸載module的生命周期

有關很少會用到的GameplayModule,游戲工程本身也是一個模塊,一般所有的模塊都是用給這個游戲模塊的,很少會反過來依賴游戲模塊

Load

LoadModule

需要選擇自己的module是在什么時候被加載的和面向什么target,通過選擇Type,最常用的是Runtime和Editor

Depend

depend

只有在依賴鏈上的模塊才會被編譯

通過添加DependencyModuleNames來配置依賴,如果沒有模塊依賴你的模塊,也可以添加Target.cs

PCH

Prcompiled Header

一般的頭文件不會自己編譯,而是在cpp引入的時候編譯

這樣的話就有一個很大的頭文件重復編譯量

讓頭文件只編譯一次

PCH定義了一個頭文件,包含了所有最常用的頭文件,然后他們會先於所有的文件編譯,他們不會重編,除非他們引入的頭文件發生了改變

必須注意的是,如果PCH重編了,所有的這個模塊的CPP文件都會重編,最好是用於引擎的頭文件或者非常少改動的頭文件

有幾種PCH,

private PCH

構建你模塊自己的PCH,把他定義在Build.cs文件里

不應該在任何頭文件或者CPP文件中引入PCH文件,他們會由UBT工具自動注入到你的模塊里

PCH是一種優化層面的東西

你的代碼寫法應該是就算PCH關掉了也能正常跑

shared PCH

除了自己定義PCH之外也可使用別人定義的PCH,模塊自己定義的SharePCH不能給自己用,只能給依賴了這個模塊的模塊使用

只有引擎模塊才能創建Share PCH

Private PCH 和 Shared PCH又是什么?有啥用?

答:它倆是特殊一點的PCH,只需記住幾(×)1(√)點,

Private PCH是給本模塊用的PCH,Shared PCH是給依賴本模塊的模塊用的PCH
一個模塊可以使用其他模塊定義的Shared PCH
一個模塊不能使用自己定義的Shared PCH
模塊對PCH的選擇只有三個:
-使用本模塊定義的Private PCH
-使用引擎自動從**本模塊依賴的模塊**定義的Shared PCH中,選出一個最佳PCH
-不使用PCH

兩者需要在模塊的build.cs文件中手動指定

UE會自動選擇最佳的SharePCH以便盡可能多的覆蓋本模塊用到的頭文件

Shared PCH的選擇范圍是本模塊依賴的模塊中定義的Shared PCH

假如模塊A依賴Slate,Core以及CoreUOject模塊,且沒定義Private PCH,
且只有Slate及Core模塊中定義了Shared PCH,
那么,A的Shared PCH就只能從Slate, Core兩個模塊中選
選哪一個呢?

基於得分來選擇——以它倆依賴的<定義了Shared PCH的>模塊數量來作為它們的分數

假設Core模塊依賴了TraceLog, Json,假如只有TraceLog模塊中定義了Shared PCH,
那么它得1分

假設Slate模塊依賴了Core, SourceControl, Json模塊,假如Json模塊中定義了Shared PCH,
那么它得2分(Core 1 + Json 1)

而且很容易看出,由於Slate的依賴項里包含了Core,那么它Shared PCH很可能包含了大部分Core模塊里的頭文件,以及其它額外的頭文件,這樣,我們就會理所當然的選擇使用Slate的Shared PCH,因為我們的模塊使用到的頭文件,也在Slate的Shared PCH里的概率更大。

因此我們將會選擇Slate模塊的Shared PCH作為本模塊的PCH。

PCH使用模式只選擇UseExplicitOrSharePCHs,這個模式下,你沒設置PCH就會使用引擎PCH,你設置了PrivatePCH就可以使用


免責聲明!

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



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