創作內容

2 GP

[UE4]GameModule與Plugin

作者:dorgon│2017-06-22 13:55:07│巴幣:4│人氣:639
部落格版本


=================================

當專案建立的時候,引擎會自動產生一個同名的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:

IMPLEMENT_MODULE定義
#define IMPLEMENT_PRIMARY_GAME_MODULE( ModuleImplClass, ModuleName, GameName ) \
IMPLEMENT_GAME_MODULE( ModuleImplClass, ModuleName )
 
#define IMPLEMENT_GAME_MODULE( ModuleImplClass, ModuleName ) \
IMPLEMENT_MODULE( ModuleImplClass, ModuleName )
 
#define IMPLEMENT_MODULE( ModuleImplClass, ModuleName ) \
extern “C" DLLEXPORT IModuleInterface* InitializeModule() \
{ \
return new ModuleImplClass(); \
} \
PER_MODULE_BOILERPLATE \
PER_MODULE_BOILERPLATE_ANYLINK(ModuleImplClass, ModuleName)
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。

IMPLEMENT_APPLICATION定義
#if IS_MONOLITHIC
 
#define IMPLEMENT_APPLICATION( ModuleName, GameName ) \
/* For monolithic builds, we must statically define the game’s name string (See Core.h) */ \
TCHAR GInternalGameName[64] = TEXT( GameName ); \
IMPLEMENT_DEBUGGAME() \
IMPLEMENT_FOREIGN_ENGINE_DIR() \
IMPLEMENT_GAME_MODULE(FDefaultGameModuleImpl, ModuleName) \
PER_MODULE_BOILERPLATE \
FEngineLoop GEngineLoop;
 
#else
 
#define IMPLEMENT_APPLICATION( ModuleName, GameName ) \
/* For non-monolithic programs, we must set the game’s name string before main starts (See Core.h) */ \
struct FAutoSet##ModuleName \
{ \
FAutoSet##ModuleName() \
{ \
FCString::Strncpy(GInternalGameName, TEXT( GameName ), ARRAY_COUNT(GInternalGameName)); \
} \
} AutoSet##ModuleName; \
PER_MODULE_BOILERPLATE \
PER_MODULE_BOILERPLATE_ANYLINK(FDefaultGameModuleImpl, ModuleName) \
FEngineLoop GEngineLoop;
 
#endif
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會更有彈性。


引用網址:https://home.gamer.com.tw/TrackBack.php?sn=3617789
All rights reserved. 版權所有,保留一切權利

相關創作

同標籤作品搜尋:Unreal Engine 4

留言共 0 篇留言

我要留言提醒:您尚未登入,請先登入再留言

2喜歡★dorgonman 可決定是否刪除您的留言,請勿發表違反站規文字。

前一篇:[UE4]Hello U...

追蹤私訊切換新版閱覽

作品資料夾

leo25127更新至1210回
穿越奇幻日常系小說『公爵家的獨生子』更新囉,來看看我們無厘頭的ㄎ一ㄤ少爺怎麼在異世界作威作福吧!看更多我要大聲說7分前


face基於日前微軟官方表示 Internet Explorer 不再支援新的網路標準,可能無法使用新的應用程式來呈現網站內容,在瀏覽器支援度及網站安全性的雙重考量下,為了讓巴友們有更好的使用體驗,巴哈姆特即將於 2019年9月2日 停止支援 Internet Explorer 瀏覽器的頁面呈現和功能。
屆時建議您使用下述瀏覽器來瀏覽巴哈姆特:
。Google Chrome(推薦)
。Mozilla Firefox
。Microsoft Edge(Windows10以上的作業系統版本才可使用)

face我們了解您不想看到廣告的心情⋯ 若您願意支持巴哈姆特永續經營,請將 gamer.com.tw 加入廣告阻擋工具的白名單中,謝謝 !【教學】