[UE4C++程序]GameModule与Plugin
當專案建立的時候,引擎會自動產生一個同名的Game Module在Source資料夾底下。我們當然可以將所有撰寫的C++類別全部放在這個Module中,可是當專案越來越大,若還是將所有的功能都放在同個Module下,不僅僅會造成管理上的混亂,而且編譯時間也會增加。
試著想像當我們隨便改動一個h檔或cpp檔的參數就要編譯幾10分鐘的情況?由于UE4在一個Module中的cpp數量到達32個的時候就會自動啟動編譯檔案合并的機制(Unity Build),雖然UE4中有參數可以控制這個機制是否啟用,但卻是舍棄掉了整體的編譯時間。因此,如何將功能適當的切到各別Module中,就變成了一件非常重要的程式架構設計問題。
那么實際上UE4的Module系統是怎么運作的呢?
每一個獨立的Module基本上是由${MODULE_NAME}.build.cs與其下的C++程式碼所組成,而在UE4中,游戲中的Module主要被分成以下幾種實作Macro定義:
- IMPLEMENT_PRIMARY_GAME_MODULE
- IMPLEMENT_GAME_MODULE
- IMPLEMENT_MODULE
到底這些實作彼此之間有什么不同?
其實,這些Macro定義在最后都會被展開成IMPLEMENT_MODULE中的實作,它們之間在本質上并沒有不同,主要是用提供Module初始化Function的實作給UE4中的ModuleManager呼叫,參照Code 2.4.1:
?
Code 2.4.1 Module的定義Macro,最后都會被展開成IMPLEMENT_MODULE中的實作。其中PER_MODULE_BOILERPLATE讓引擎有機會提供一些額外的功能給這個module,例如把原本C++中的New跟delete做Overriding,并將功能導向UE4中的記憶體管理機制。最后的PER_MODULE_BOILERPLATE_ANYLINK其實并沒有其他特別的功能,就只是用來做標示,用來說明這個Module相關的定義已經完成。
從上面的程式碼中我們可以看出,從Primary Game Module、Game Module到Module總共有三個層級的定義。只是,既然這些Module的定義做的事情都差不多,那為何引擎還要個別提供?
這邊雖然沒辦法完全的掌握設計者的意圖,但至少我們可以推敲出區分出這些Module定義名稱的好處:若以后想要在Primary Game Module或Game Module層級增加功能的時候,就不會影響到最下層的Module層級的實作。
到這里,或許有人會開始思考這幾個層級到底應該用在哪些地方。其實UE4在架構上把程式碼拆分成以下幾個部份:
- Engine:位于${UE4_ENGINE_ROOT}/Engine/Source/下面的Developer、Editor、Runtime以及ThirdParty這幾個資料夾。
- Engine Plugin:位于${UE4_ENGINE_ROOT}/Engine/Plugin/。
- Game:位于${PROJECT_NAME}/Source/。
- Game Plugin:位于${PROJECT_NAME}/Plugin/。
- Programs:位于${UE4_ENGINE_ROOT}/Engine/Source/Programs,屬于獨立運行的工具類程式,里面使用C#或C++分別進行不同的實作。
其中只有位于Game中的Module會使用IMPLEMENT_PRIMARY_GAME_MODULE跟IMPLEMENT_GAME_MODULE這2個實作,從名稱中我們可以推測出,作為主要游戲的入口的Primary Game Module只能有一個,其他則都必需設成Game Module。
其他在Engine、Engine Plugin跟Game Plugin底下的Module則都是直接使用IMPLEMENT_MODULE這個定義。
當然,就目前的引擎版本我們是可以全部都用IMPLEMENT_MODULE來實作出上面Module所有效果,但是為了往后更新引擎版本時的兼容性,建議還是照著UE4所定義出來的流程實作。
最后的Programs跟其他的Module不同,里面的C++ Module會使用IMPLEMENT_APPLICATION這個定義,參見Code 2.4.2。
?
Code 2.4.2 在UE4中,Module的Link分成Modular跟Monolithic二種方式:Modular指的是將Module編譯成各別的dynamic library再做連結;Monolithic則是指將所有的Module全部編譯到同一份Library中。其中Editor預設是Modular,而Game預設是Monolithic。
而要不要把該Module放到Plugin或者是當成Game Module,則要看這個Module需不需要用在不同的專案上使用。若是這個Module中的功能需要讓其他專案使用的話,則將該Module制作成Plugin會比單純的當成Game Module會更有彈性。
?
?
- 在UE項目添加一個新的Module
本文只簡單介紹下創建自定義模塊的方法
1. 新建項目并在Source文件夾下建立我們要添加的新模塊?
?
2. 并在新建的NewModule文件夾下創建.h .cpp .Build.cs 后綴的3個文件?
?
3.?進入VS建立NewModule(篩選器)并把剛才文件夾里新創建的3個文件拖入NewModule下?
?
4.為NewModule.Build.cs添加內容(直接從我們項目里的TestModule.Build.cs拷貝即可)?
using UnrealBuildTool;
public class NewModule: ModuleRules
{
? ? public NewModule(ReadOnlyTargetRules Target) : base(Target)
?? ?{
? ? ? ? PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;
? ? ? ? PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore" });
? ? ? ? PrivateDependencyModuleNames.AddRange(new string[] { });
? ? ? ? // Uncomment if you are using Slate UI
? ? ? ? // PrivateDependencyModuleNames.AddRange(new string[] { "Slate", "SlateCore" });
? ? ? ? // Uncomment if you are using online features
? ? ? ? // PrivateDependencyModuleNames.Add("OnlineSubsystem");
? ? ? ? // To include OnlineSubsystemSteam, add it to the plugins section in your uproject file with the Enabled attribute set to true
? ? }
}
5. 修改NewModule.h為
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "Engine.h"
#include "ModuleManager.h"
class FNewModuleModule : public IModuleInterface
{
public:
? /** IModuleInterface implementation */
? virtual void StartupModule() override;
? virtual void ShutdownModule() override;
};
?
6.修改NewModule.cpp為
// Copyright Sigurdur Gunnarsson. All Rights Reserved.?
// Licensed under the MIT License. See LICENSE file in the project root for full license information.?
#include "NewModule.h"
void FNewModuleModule::StartupModule()
{
? // This code will execute after your module is loaded into memory; the exact timing is specified in the .uplugin file per-module
}
void FNewModuleModule::ShutdownModule()
{
? // This function may be called during shutdown to clean up your module. ?For modules that support dynamic reloading,
? // we call this function before unloading the module.
}
??
IMPLEMENT_MODULE(FNewModuleModule, NewModule)
6. 進入項目的uproject內添加我們的新模塊?
?
7. 最后在項目里的.Target.cs里添加新的模塊名?
2個.Target.cs后綴的都需要添加模塊名?
8. 使用Editor在NewModule下創建Actor,重新編譯成功后,在C++ Class下就能看到新建的NewModule
?
?
總結
以上是生活随笔為你收集整理的[UE4C++程序]GameModule与Plugin的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Linux 文字雨特效
- 下一篇: C++图书管理系统_艾孜尔江撰