本隨筆介紹如何在UE4項目和插件里創建新的C++模塊的方法。因為官方引擎並沒有提供直接創建模塊的方法[1],所以通過本隨筆記錄一下通用的創建方式。
隨筆作者還在學習階段,對UE4引擎的使用和理解還不是非常透徹,難免會在隨筆內容里出現技術上或書寫上的問題,如果出現了類似的問題歡迎在評論區或者私信討論。
前置工作
我已經提前新建了一個名為“AddModuleTest”的UE4C++項目,並且在其中新建了一個名為“ModulePlugin”的C++插件,而在本隨筆的最后我們會創建一個新的名為“NewModule”的模塊。因為模塊是在UE4C++代碼里面才會有的概念,所以無論是要在項目或者插件里添加模塊,都需要是C++類型而不能是藍圖類型。在項目里添加模塊並不需要其所有插件都為C++插件,甚至都不需要插件,但是如果要在插件里面添加模塊的話就一定需要項目是C++類型,因為我們需要用到項目的Visual Studio工程去構建新建的模塊。本隨筆的大部分篇幅我會以新建插件模塊的方法去描述,因為項目模塊的創建方法和插件模塊的創建方法一致,只是在部分設置上會有所區別,區別的內容我會在隨筆最后介紹。
新建模塊文件夾
插件(Plugin)或項目都是由模塊(Module)組成,因此也可以說每個插件或項目都會至少包含一個模塊,在文件資源管理器展示的目錄結構里,每個模塊需要用到的所有文件都會被包含到被命名為模塊名字的文件夾內,而這些文件夾都會被放到源碼文件夾里,該文件夾被命名為“Source”。項目有自己的唯一一個源碼文件夾,插件同樣也有唯一的源碼文件夾:
新建的模塊文件夾也需要放置到源碼文件里面,在本隨筆中我新建了一個名為“NewModule”的模塊文件夾在插件源碼文件夾里:
可從上圖里面看到,插件源碼文件夾里面已經存在了一個模塊文件夾“ModulePlugin”,這些模塊文件夾是默認由引擎創建的,且名字與插件名稱一致。新建的模塊名稱沒有任何硬性的規定。
新建模塊文件
不論是在項目里新建模塊還是在插件里新建模塊,模塊所需要的的基礎文件一共有三個,一個是模塊定義頭文件(.h),一個是模塊定義源文件(.cpp),這兩個文件統稱為模塊定義文件,還有一個模塊構建文件(.Build.cs)。
新建模塊定義頭文件
模塊定義頭文件是模塊定義所需要用到的頭文件,該頭文件的命名格式為“<ModuleName>.h”,其中尖括號的文字表示可以被任意替換,一般來說是替換為模塊的名字。需要注意的是尖括號本身並不是文字的內容,因此也需要被替換掉。在本隨筆中我新建了一個名為“NewModule.h”的模塊定義頭文件:
該頭文件的作用主要是用來聲明我們要定義的模塊在C++代碼里的類,模塊定義頭文件的內容格式如下:
// Copyright message here.
#pragma once
#include "Modules/ModuleManager.h"
class <ModuleClassName> : public IModuleInterface
{
public:
virtual void StartupModule();
virtual void ShutdownModule();
};
其中尖括號包含的文字<ModuleClassName>
是可以任意替換的內容,一般是替換為模塊的類名,且尖括號也需要被替換掉。這里需要注意的是,實際的文字是模塊的類名而不是模塊的名稱。本隨筆中我們要新建一個名稱為“NewModule”的模塊,按照UE4C++代碼規范編寫的話那么這個類名就是FNewModule,也就是說我們模塊定義頭文件的內容應該是下面的格式:
// Copyright message here.
#pragma once
#include "Modules/ModuleManager.h"
class FNewModule : public IModuleInterface
{
public:
virtual void StartupModule();
virtual void ShutdownModule();
};
新建模塊定義源文件
模塊定義源文件是定義模塊定義頭文件里聲明了的模塊類所需要用到的文件,該源文件的命名格式為“<ModuleName>.cpp”,在本隨筆中我們新建的模塊定義源文件的名稱應為“NewModule.cpp”:
模塊定義源文件的內容格式如下:
// Copyright message here.
#pragma once
#include "<ModuleName>.h"
void <ModuleClassName>::StartupModule()
{
}
void <ModuleClassName>::ShutdownModule()
{
}
IMPLEMENT_MODULE(<ModuleClassName>, <ModuleName>)
其中尖括號包含的文字<ModuleName>
即為模塊名字,這里通俗來講其實就是需要包含模塊定義頭文件。額外的尖括號文字<ModuleClassName>
即為模塊的類名,最后一行的代碼是一個宏,該宏實現了將模塊類暴露給項目使用的功能,因此會接收兩個參數,一個是要暴露的模塊類的名字,一個是暴露后模塊的名字。在本隨筆中我們的模塊定義源文件內容就會是如下格式:
// Copyright message here.
#pragma once
#include "NewModule.h"
void FNewModule::StartupModule()
{
}
void FNewModule::ShutdownModule()
{
}
IMPLEMENT_MODULE(FNewModule, NewModule)
新建模塊構建文件
模塊構建文件是一個特殊的模塊文件,該文件由C#編寫,其作用是控制該模塊如何與其他模塊進行交互,模塊構建文件的命名格式為“<ModuleName>.Build.cs”,在本隨筆中我們新建的模塊構建文件名稱就為“NewModule.Build.cs”:
模塊構建文件的內容格式如下:
// Copyright message here
using UnrealBuildTool;
public class <ModuleName> : ModuleRules
{
public <ModuleName>(ReadOnlyTargetRules Target) : base(Target)
{
PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs;
PublicDependencyModuleNames.AddRange(new string[] { "Core" });
PrivateDependencyModuleNames.AddRange(new string[] { "CoreUObject", "Engine", "Slate", "SlateCore" });
}
}
模塊構建文件看起來很長,實際上需要改寫的地方就只有兩處,只需要將尖括號包含的文字<ModuleName>
改寫為實際的模塊名稱即可,在本隨筆中我們的模塊構建文件的內容格式如下:
// Copyright message here
using UnrealBuildTool;
public class NewModule : ModuleRules
{
public NewModule(ReadOnlyTargetRules Target) : base(Target)
{
PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs;
PublicDependencyModuleNames.AddRange(new string[] { "Core" });
PrivateDependencyModuleNames.AddRange(new string[] { "CoreUObject", "Engine", "Slate", "SlateCore" });
}
}
添加新模塊信息
在插件描述文件(Plugin Descriptor)里添加新的模塊描述符:
其中被選中的部分即為我們需要手動添加的部分。
構建新添加的模塊
打開項目的Visual Studio工程,重新構建我們的項目(“生成(Build)”或者“重新生成(Rebuild)”都可以),構建完成之后即可在項目里面找到我們新創建的模塊:
添加項目模塊與添加插件模塊的區別
- 在新建模塊文件夾小節,新創建的模塊文件夾要放到項目源碼文件夾里面而不是插件源碼文件夾。
- 在添加新模塊信息小節,添加新的模塊描述符應該在項目描述文件里而不是插件描述文件里。
- 需要額外在項目目標文件里添加新建的模塊名稱。項目目標文件被放置在項目源碼文件夾里,是以“.Target.cs”結尾的文件,默認情況下項目會存在兩個目標文件:“<ProjectName>.Target.cs”和“<ProjectName>Editor.Target.cs”,這兩個目標文件分別指定了在Game模式和Editor模式下需要編譯的模塊名稱,根據需要可以添加新的目標文件,除了Editor類型,還可以是Client類型和Server類型等等。關於項目目標文件的詳細信息請查閱官方文檔。在我們的例子里,我們只需要在Editor模式下編譯該模塊即可,也就是在“<ProjectName>Editor.Target.cs”目標文件里添加我們的模塊即可:
- 完成上述的操作之后執行構建新添加的模塊小節里的操作,即可實現在項目里添加模塊。
編寫本隨筆時官方引擎最新版本為4.26。 ↩︎