| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Name | Name | Last commit date | ||
|---|---|---|---|---|
An Unreal Engine Module is the fundamental unit of code organization, similar to Libraries or Packages in other programming languages. Each module is an independent compilation unit with the following characteristics:
Source/
└── [ModuleName]/
├── [ModuleName].Build.cs # Build configuration file
├── Public/ # Public header files
│ ├── [ModuleName]Module.h # Main module header
│ └── [PublicClass].h # Other public classes
└── Private/ # Private implementation files
├── [ModuleName]Module.cpp # Module implementation
└── [PrivateClass].cpp # Other implementation files
📝 Important Note: The module names Auto and Manual in this project are chosen purely to demonstrate two different methods of module creation:
- Auto: Created using IDE (JetBrains Rider) with automatic generation
- Manual: Created manually with full control over the process
These names have no special meaning regarding module dependencies or functionality. The same principles apply to any module names (e.g., ModuleA/ModuleB, GameplayCore/UISystem, etc.). The dependency relationship (Manual depends on Auto) is simply for demonstration purposes and could easily be reversed or applied to any other module combination.
FirstModule/Source/
├── Auto/ # IDE-created module
│ ├── Auto.Build.cs
│ ├── Public/
│ │ ├── AutoModule.h
│ │ ├── AutoCppOnly.h
│ │ └── AutoExposed.h
│ └── Private/
│ ├── AutoModule.cpp
│ ├── AutoCppOnly.cpp
│ ├── AutoExposed.cpp
│ ├── AutoInternal.cpp
│ └── AutoInternal.h
├── Manual/ # Manually created module
│ ├── Manual.Build.cs
│ ├── Public/
│ │ ├── ManualModule.h
│ │ ├── ManualCppOnly.h # C++ only classes
│ │ └── ManualExposed.h # Blueprint compatible
│ └── Private/
│ ├── ManualModule.cpp
│ ├── ManualCppOnly.cpp
│ ├── ManualExposed.cpp
│ ├── ManualInternal.cpp
│ └── ManualInternal.h # Internal implementation
├── Migrate/ # Migrated module (example)
│ ├── Migrate.Build.cs
│ ├── Public/
│ │ ├── Migrate.h
│ │ └── MigrateActor.h
│ └── Private/
│ ├── Migrate.cpp
│ └── MigrateActor.cpp
└── FirstModule/ # Main game module
├── FirstModule.Build.cs
├── FirstModule.cpp
└── FirstModule.h
Let's examine how the Manual module was created in this project:
Create a new module folder under the Source/ directory:
Source/
└── Manual/
├── Public/
└── Private/
Create Source/Manual/Manual.Build.cs:
//----------------------------------------------------------------------------------------------------
// Manual.Build.cs
//----------------------------------------------------------------------------------------------------
using UnrealBuildTool;
public class Manual : ModuleRules
{
public Manual(ReadOnlyTargetRules Target) : base(Target)
{
PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;
PublicDependencyModuleNames.AddRange([
"Core",
"Auto" // This module depends on Auto module
]);
PrivateDependencyModuleNames.AddRange([
"CoreUObject",
"Engine"
]);
}
}Create Source/Manual/Public/ManualModule.h:
//----------------------------------------------------------------------------------------------------
// ManualModule.h
//----------------------------------------------------------------------------------------------------
#pragma once
#include <CoreMinimal.h>
#include <Modules/ModuleManager.h>
DECLARE_LOG_CATEGORY_EXTERN(LogManual, Log, All);
class MANUAL_API FManualModule final : public IModuleInterface
{
public:
virtual void StartupModule() override;
virtual void ShutdownModule() override;
};Create Source/Manual/Private/ManualModule.cpp:
//----------------------------------------------------------------------------------------------------
// ManualModule.cpp
//----------------------------------------------------------------------------------------------------
#include "ManualModule.h"
#include <Modules/ModuleManager.h>
DEFINE_LOG_CATEGORY(LogManual);
#define LOCTEXT_NAMESPACE "FManualModule"
void FManualModule::StartupModule()
{
UE_LOG(LogManual, Warning, TEXT("FManualModule::StartupModule()"));
}
void FManualModule::ShutdownModule()
{
UE_LOG(LogManual, Warning, TEXT("FManualModule::ShutdownModule()"));
}
#undef LOCTEXT_NAMESPACE
IMPLEMENT_MODULE(FManualModule, Manual)FirstModule.uproject:
{
"FileVersion": 3,
"EngineAssociation": "5.6",
"Modules": [
{
"Name": "FirstModule",
"Type": "Runtime",
"LoadingPhase": "Default"
},
{
"Name": "Auto",
"Type": "Runtime",
"LoadingPhase": "Default"
},
{
"Name": "Manual",
"Type": "Runtime",
"LoadingPhase": "Default"
}
]
}FirstModule.Target.cs:
//----------------------------------------------------------------------------------------------------
// FirstModule.Target.cs
//----------------------------------------------------------------------------------------------------
using UnrealBuildTool;
public class FirstModuleTarget : TargetRules
{
public FirstModuleTarget(TargetInfo Target) : base(Target)
{
Type = TargetType.Game;
DefaultBuildSettings = BuildSettingsVersion.V5;
IncludeOrderVersion = EngineIncludeOrderVersion.Unreal5_6;
ExtraModuleNames.Add("FirstModule");
RegisterModulesCreatedByRider();
}
private void RegisterModulesCreatedByRider()
{
ExtraModuleNames.AddRange(["Auto", "Manual"]);
}
}For creating your own modules, use this template:
// YourModuleName.Build.cs
using UnrealBuildTool;
public class YourModuleName : ModuleRules
{
public YourModuleName(ReadOnlyTargetRules Target) : base(Target)
{
PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs;
PublicDependencyModuleNames.AddRange([
"Core"
]);
PrivateDependencyModuleNames.AddRange([
"CoreUObject",
"Engine"
]);
}
}The Auto module in this project was created using Rider:


//----------------------------------------------------------------------------------------------------
// Auto.Build.cs (Generated by Rider)
//----------------------------------------------------------------------------------------------------
using UnrealBuildTool;
public class Auto : ModuleRules
{
public Auto(ReadOnlyTargetRules Target) : base(Target)
{
PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;
PublicDependencyModuleNames.AddRange([
"Core"
]);
PrivateDependencyModuleNames.AddRange([
"CoreUObject",
"Engine"
]);
}
}//----------------------------------------------------------------------------------------------------
// AutoModule.h (Generated by Rider)
//----------------------------------------------------------------------------------------------------
#pragma once
#include <CoreMinimal.h>
#include <Modules/ModuleManager.h>
DECLARE_LOG_CATEGORY_EXTERN(LogAuto, Log, All);
class FAutoModule final : public IModuleInterface
{
public:
virtual void StartupModule() override;
virtual void ShutdownModule() override;
};//----------------------------------------------------------------------------------------------------
// AutoModule.cpp (Generated by Rider)
//----------------------------------------------------------------------------------------------------
#include "AutoModule.h"
#include <Modules/ModuleManager.h>
DEFINE_LOG_CATEGORY(LogAuto);
#define LOCTEXT_NAMESPACE "FAutoModule"
void FAutoModule::StartupModule()
{
UE_LOG(LogAuto, Warning, TEXT("FAutoModule::StartupModule()"));
}
void FAutoModule::ShutdownModule()
{
UE_LOG(LogAuto, Warning, TEXT("FAutoModule::ShutdownModule()"));
}
#undef LOCTEXT_NAMESPACE
IMPLEMENT_MODULE(FAutoModule, Auto)


Sometimes you need to move or migrate an existing module from one project to another. This process involves copying the module files and updating the target project's configuration. The Migrate module in this project demonstrates how an external module can be integrated.
📝 Migration Note: Module migration is useful when you want to:
- Share modules between different projects
- Move modules from an experimental project to production
- Reuse existing functionality in new projects
- Backup and restore specific modules
The first step is to copy the entire module folder from the source project:
SourceProject/Source/
└── Migrate/ # Copy this entire folder
├── Migrate.Build.cs
├── Public/
│ ├── Migrate.h
│ └── MigrateActor.h
└── Private/
├── Migrate.cpp
└── MigrateActor.cpp
Paste the copied module folder to the target project:
TargetProject/Source/ ├── Auto/ # Existing module ├── Manual/ # Existing module ├── Migrate/ # ✅ Newly migrated module │ ├── Migrate.Build.cs │ ├── Public/ │ │ ├── Migrate.h │ │ └── MigrateActor.h │ └── Private/ │ ├── Migrate.cpp │ └── MigrateActor.cpp └── FirstModule/ # Main game module
After copying the files, you need to register the migrated module in the target project:
Add the new module to FirstModule.uproject:
{
"FileVersion": 3,
"EngineAssociation": "5.6",
"Modules": [
{
"Name": "FirstModule",
"Type": "Runtime",
"LoadingPhase": "Default"
},
{
"Name": "Auto",
"Type": "Runtime",
"LoadingPhase": "Default"
},
{
"Name": "Manual",
"Type": "Runtime",
"LoadingPhase": "Default"
},
{
"Name": "Migrate", // ✅ Add this entry
"Type": "Runtime",
"LoadingPhase": "Default"
}
]
}Add the module name to both FirstModule.Target.cs and FirstModuleEditor.Target.cs:
FirstModule.Target.cs:
private void RegisterModulesCreatedByRider()
{
ExtraModuleNames.AddRange(["Auto", "Manual", "Migrate"]); // ✅ Add "Migrate"
}FirstModuleEditor.Target.cs:
private void RegisterModulesCreatedByRider()
{
ExtraModuleNames.AddRange(["Auto", "Manual", "Migrate"]); // ✅ Add "Migrate"
}After updating the configuration files:
To confirm the migration was successful:
LogTemp: Warning: MigrateActor::AMigrateActor
Symptoms: Compilation errors about missing includes or undefined classes Solution: Ensure all dependency modules exist in the target project or update Build.cs
Symptoms: Linker errors or undefined symbols Solution: Verify the MIGRATE_API macro is correctly defined and used
Symptoms: Module doesn't appear in the modules list Solution: Double-check .uproject and Target.cs entries, then regenerate project files
When migrating between different UE versions:
When migrating a module that depends on other custom modules:
Module migration is a powerful feature that enables code reuse across projects and helps maintain a modular architecture. The Migrate module in this project serves as a practical example of how external modules can be seamlessly integrated into existing projects.
📝 Naming Convention Note: In this project, "Manual depends on Auto" is purely for demonstration. The dependency direction has nothing to do with how the modules were created (manually vs. IDE). In real projects, you might have:
- GameplayCore depends on UtilityLibrary
- UISystem depends on GameplayCore
- AudioManager depends on ConfigurationModule
- PlayerController depends on InputManager
The dependency direction and module names should reflect your actual project architecture, not the creation method. You could equally have:
- Auto depends on Manual
- ModuleA depends on ModuleB
- Any meaningful combination based on your project needs
Manual.Build.cs shows the dependency:
PublicDependencyModuleNames.AddRange([
"Core",
"Auto" // Manual depends on Auto
]);ManualExposed.h includes AutoCppOnly:
//----------------------------------------------------------------------------------------------------
// ManualExposed.h
//----------------------------------------------------------------------------------------------------
#pragma once
#include <CoreMinimal.h>
#include "AutoCppOnly.h" // Include from Auto module
#include <ManualExposed.generated.h>
UCLASS(Blueprintable)
class MANUAL_API AManualExposed : public AActor
{
GENERATED_BODY()
public:
AManualExposed();
UFUNCTION(BlueprintCallable, Category = "Manual")
void DoManualExposed() const;
FAutoCppOnly AutoCppOnly; // Using class from Auto module
};ManualExposed.cpp uses the Auto module class:
//----------------------------------------------------------------------------------------------------
// ManualExposed.cpp
//----------------------------------------------------------------------------------------------------
#include "ManualExposed.h"
#include "ManualModule.h"
AManualExposed::AManualExposed()
{
UE_LOG(LogManual, Warning, TEXT("AManualExposed::AManualExposed()"));
}
void AManualExposed::DoManualExposed() const
{
UE_LOG(LogManual, Warning, TEXT("AManualExposed::DoManualExposed()"));
AutoCppOnly.DoAutoCppOnly(); // Call method from Auto module
}Based on this project's structure, here's the three-tier classification:
Purpose: High-performance C++ API for other modules Features:
//----------------------------------------------------------------------------------------------------
// ManualCppOnly.h
//----------------------------------------------------------------------------------------------------
#pragma once
#include <CoreMinimal.h>
class MANUAL_API FManualCppOnly
{
public:
FManualCppOnly();
void DoManualCppOnly();
};//----------------------------------------------------------------------------------------------------
// ManualCppOnly.cpp
//----------------------------------------------------------------------------------------------------
#include "ManualCppOnly.h"
#include "ManualModule.h"
FManualCppOnly::FManualCppOnly()
{
UE_LOG(LogManual, Warning, TEXT("FManualCppOnly::FManualCppOnly()"));
}
void FManualCppOnly::DoManualCppOnly()
{
UE_LOG(LogManual, Warning, TEXT("FManualCppOnly::DoManualCppOnly()"));
}Purpose: Blueprint-compatible game logic Features:
//----------------------------------------------------------------------------------------------------
// ManualExposed.h
//----------------------------------------------------------------------------------------------------
#pragma once
#include <CoreMinimal.h>
#include "AutoCppOnly.h"
#include <ManualExposed.generated.h>
UCLASS(Blueprintable)
class MANUAL_API AManualExposed : public AActor
{
GENERATED_BODY()
public:
AManualExposed();
UFUNCTION(BlueprintCallable, Category = "Manual")
void DoManualExposed() const;
FAutoCppOnly AutoCppOnly;
};Purpose: Internal module implementation details Features:
//----------------------------------------------------------------------------------------------------
// ManualInternal.h
//----------------------------------------------------------------------------------------------------
#pragma once
#include <CoreMinimal.h>
class FManualInternal
{
FManualInternal();
void DoManualInternal() const;
};Source/Manual/
├── Public/ # External interface
│ ├── ManualModule.h # Module definition
│ ├── ManualCppOnly.h # C++ only classes
│ └── ManualExposed.h # Blueprint compatible
└── Private/ # Internal implementation
├── ManualModule.cpp # Module implementation
├── ManualCppOnly.cpp # C++ implementation
├── ManualExposed.cpp # Blueprint class implementation
├── ManualInternal.h # Internal definitions
└── ManualInternal.cpp # Internal implementation
// Public class - can be used by other modules
class MANUAL_API FManualCppOnly // Has MANUAL_API macro
{
// Accessible from other modules
};
// Private class - internal use only
class FManualInternal // No API macro, in Private folder
{
// Internal use only
};// In ManualModule.h
DECLARE_LOG_CATEGORY_EXTERN(LogManual, Log, All);
// In ManualModule.cpp
DEFINE_LOG_CATEGORY(LogManual);
// Usage throughout the module
UE_LOG(LogManual, Warning, TEXT("FManualCppOnly::DoManualCppOnly()"));Symptoms: Game startup shows module not found
Solutions:
Symptoms: Cannot find header files or linking errors
Solutions:
Symptoms: Module A depends on B, B also depends on A
Solutions:
Symptoms: C++ classes not visible in Blueprint
Solutions:
Example from ManualExposed (Working Blueprint Class):
UCLASS(Blueprintable) // Makes class available in Blueprint
class MANUAL_API AManualExposed : public AActor
{
GENERATED_BODY()
public:
UFUNCTION(BlueprintCallable, Category = "Manual") // Callable from Blueprint
void DoManualExposed() const;
};Symptoms: Constructor logs appear multiple times before the game starts
LogManual: Warning: AManualExposed::AManualExposed() LogManual: Warning: AManualExposed::AManualExposed() LogManual: Warning: AManualExposed::AManualExposed()
This is normal behavior! UE calls constructors for:
Best Practices:
AManualExposed::AManualExposed()
{
// ✅ Good: Just log and set defaults
UE_LOG(LogManual, Warning, TEXT("AManualExposed::AManualExposed()"));
// ❌ Bad: Don't do game logic here
// StartGameplay();
// LoadAssets();
}
void AManualExposed::BeginPlay()
{
Super::BeginPlay();
// ✅ Good: Game logic goes here
StartGameplay();
}// In ManualModule.cpp
DEFINE_LOG_CATEGORY(LogManual);// In ManualModule.cpp
#define LOCTEXT_NAMESPACE "FManualModule"
// ... module code ...
#undef LOCTEXT_NAMESPACE// In ManualModule.cpp
IMPLEMENT_MODULE(FManualModule, Manual)This handbook is based on the real FirstModule project, demonstrating:
Through proper module design, you can:
Remember, good module design is the foundation of successful UE projects. Start with small modules and gradually build your modular architecture.
Feel free to contribute to this handbook by:
This handbook is provided under the Apache 2.0 License. Feel free to use, modify, and distribute it for educational purposes.
| Back | FazBrowse Home | New Git URL |