Skip to main content

Resource

Module Organization

When to split modules, what types exist, how dependencies work, and how to name them. The stuff that's hard to change later.

Module types

Unreal Engine has several module types. Each one loads at a different point in the engine lifecycle and has different constraints on what it can reference.

Type
Loads When
Ships in Packaged Build
Use Case
RuntimeAlwaysYesCore gameplay code, systems that run in shipping builds
RuntimeAndProgramAll targets including standalone programsYesUtility libraries shared between the game, editor, and standalone UE programs like UnrealPak
EditorEditor onlyNoCustom editor tools, detail panels, asset factories
DeveloperToolNon-shipping buildsNoDebug tools, test harnesses, dev cheats. Note: the old Developer type is deprecated since 4.24.
UncookedOnlyUncooked editor sessionsNoCustom Blueprint node types (K2Node), editor-only graph systems
ProgramStandalone programs onlyDependsCommandlets, automation tools

When to split a module

Start with one Runtime module per project. Split when you have a concrete reason, not preemptively.

Split when

  • +Editor-only code is mixed with runtime code
  • +Two teams need independent compile and iteration cycles
  • +A system is reusable across projects (extract to plugin)
  • +Compile times are noticeably degrading
  • +A subsystem has no business depending on another

Don't split when

  • −You're just organizing files (use folders instead)
  • −The split would create circular dependencies
  • −The module would have fewer than 5-10 source files
  • −You're doing it because another project did

Module naming

Module names are PascalCase with no underscores. The project or plugin name typically appears as a prefix to avoid collisions with engine modules.

Pattern
Example
Notes
Primary game moduleMyGameMatches the .uproject name. Created by default.
Feature moduleMyGameInventoryProject prefix + feature name.
Editor moduleMyGameEditorSuffix with Editor. Contains detail panels, asset factories.
Plugin runtime moduleSmartAIPlugin name is the module name for single-module plugins.
Plugin editor moduleSmartAIEditorSuffix with Editor, same as game modules.
Shared types moduleMyGameCoreLightweight module for interfaces, structs, and enums that other modules depend on.

Dependency rules

Module dependencies are declared in .Build.cs files. Dependencies flow in one direction. Circular dependencies between modules won't compile.

  • 01Use PublicDependencyModuleNames when your public headers expose types from the dependency.
  • 02Use PrivateDependencyModuleNames when only your .cpp files need the dependency. This is the safer default.
  • 03Editor modules can depend on Runtime modules, never the reverse.
  • 04If two modules need each other's types, extract the shared types into a Core module that both depend on.
  • 05PrivateIncludePathModuleNames makes include paths available for forward declarations only. Your .cpp files can't call into that module without a proper dependency entry.

Module file structure

Each module has a standard file layout. The module name matches the folder name and the .Build.cs file name.

Source/
MyGameInventory/
MyGameInventory.Build.cs // Module rules
Public/ // Headers other modules can include
InventoryComponent.h
InventoryTypes.h
Private/ // Internal implementation
MyGameInventoryModule.cpp // IMPLEMENT_MODULE
InventoryComponent.cpp
InventoryManagerSubsystem.cpp

Anti-patterns

One class per module
Modules have overhead. If a module only contains one or two classes, it probably doesn't need to be its own module.
Circular dependencies
Extract shared types into a Core/Types module. If two features need each other, they may belong in the same module.
Everything in Public/
Only headers that other modules need belong in Public/. Internal classes go in Private/. This keeps the API surface small.
Editor dependencies in Runtime
Runtime modules must never depend on Editor modules. The code won't link in shipping builds.
Depending on plugin internals
Only depend on a plugin's Public API. Referencing Private/ headers of another module breaks on any refactor.

Unreal Directive is free and ad-free.

If it saved you time, you can help keep it that way.

Donate