
런타임(게임 실행시)에 필요한 코드들
Core : 문자열 처리, 컨테이너(TArray, TMap), 로깅, 수학 함수
CoreUObject : UObject 시스템, 리플렉션, 가비지 컬렉션, 직렬화
Engine : 액터, 컴포넌트, 월드, 레벨 등 게임 프레임워크 핵심
Renderer : 렌더링 시스템 (Nanite, Lumen 포함)
PhysicsCore : 물리 엔진 인터페이스
AudioMixer : 오디오 시스템
Networking : 네트워크 복제, RPC
언리얼 에디터 전용 코드. 패키징 시 필요없으므로 제외됨
UnrealEd : 에디터 핵심 프레임워크
LevelEditor : 레벨 편집 기능
MaterialEditor : 머티리얼 편집
BlueprintGraph : 블루프린트 노드 그래프 시스템
Kismet : 블루프린트 VM과 컴파일러
PropertyEditor : 디테일 패널
개발 중에만 필요한 코드(프로파일링 도구, 자동화 테스트 등)
Shipping 빌드에서 제외
빌드 및 실행 도구에 필요한 모듈들이 존재
UnrealBuildTool (UBT) : 빌드 시스템
UnrealHeaderTool (UHT) : 리플렉션 코드 생성기
코드의 기본 빌딩 블록
특정 기능(예: UI, AI, 물리)을 독립된 단위로 묶음
각 모듈은 각각의 build.cs파일을 가지고, 해당파일에 모듈의 빌드 규칙과 의존성을 정의함
하나의 모듈이 하나의 dll파일(정적 라이브러리)이 됨
프로젝트를 생성하면 기본적으로 ProjectName이라는 메인 게임 모듈이 생김
그래서 Games\ProjectName\Source에 Build.cs파일이 존재했던 것
위에서 본, 엔진 소스코드 폴더들도 여러 모듈들을 폴더화 한 것

하나 이상의 모듈을 담는 패키지
프로젝트와 완전히 독립적으로 존재할 수 있는 기능 묶음
한 프로젝트에서 만든 플러그인을 다른 프로젝트로 쉽게 복사해서 사용 가능
코드(모듈)뿐만 아니라 블루프린트, 에셋(텍스처, 모델링), 설정값 등을 모두 포함할 수 있음
에디터에서 쉽게 On/Off가 가능
.uplugin : 플러그인의 메타데이터(이름, 버전, 모듈 목록 등)를 담은 JSON 형식의 파일 (Plugins 폴더에 존재)

컴파일 시간 단축
모든 코드를 다 컴파일하면 시간이 엄청 오래 걸림
코드를 모듈화 하여, 수정된 모듈만 컴파일하여 시간을 단축함
특히 엔진 소스코드를 모듈화하여 시간을 매우 단축
기능 단위의 캡슐화
복잡한 내부구조는 private에 두고, public을 통해서만 다른 모듈에서 include가능하도록 함
따라서 내부구조가 수정되더라도, 외부 interface(public)는 그대로이기 때문에 해당 모듈을 include한 다른 모듈에서 재컴파일 안 해줘도 됨
MyAIModule/
├── Public/
│ ├── MyAIController.h // 외부에서 사용할 클래스
│ └── AITypes.h // 공개 타입 정의
└── Private/
├── BehaviorTree/ // 내부 구현
│ ├── BTNode_Attack.cpp
│ └── BTNode_Attack.h
├── Utility/ // 내부 유틸리티
│ └── AIMathUtils.h
└── MyAIController.cpp
블루프린트와 리플렉션의 연결
UnrealHeaderTool(UHT)가 모듈 단위로 동작하므로 필요함
Build.cs에 의존성이 설정되지 않으면 UHT가 해당 헤더를 인식하지 못함.
"UCLASS가 인식되지 않습니다" 에러의 흔한 원인: 모듈 의존성 설정 누락
// Runtime 모듈 선언 예시
{
"Name": "MyGame",
"Type": "Runtime",
"LoadingPhase": "Default"
}
모듈 타입 종류
Runtime : 런타임중에 사용될 모듈. 패키징에 포함됨
Editor : 에디터 전용 모듈. 패키징에 포함 안 됨
Developer : 개발 빌드 전용(프로파일링용). Development모드에서만 포함됨
LoadingPhase : 모듈이 언제 로딩될 지에 대한 옵션. 보통 Default로 설정
EarliestPossible : 가장 빠른 시점 (저수준 모듈)
PostConfigInit : 설정 시스템 초기화 직후
PreDefault : Default보다 먼저 (커스텀 애니메이션 노드 등)
Default : 일반적인 게임플레이 모듈 (기본값)
PostEngineInit : 엔진 완전 초기화 후
None : 자동 로드 안 함 (수동 로드 필요)
UCLASS()
class MYGAME_API AMyCharacter : public ACharacter
{
// ...
};
MYGAME_API의 의미가 해당 모듈에서 클레스에 접근 가능하게 하는 매크로// MyPlugin.uplugin
{
// ... //
"CanContainContent": true, // Content 폴더(에셋) 포함 가능 여부
"Modules": [ // Plugin에 포함된 모듈 목록
{
"Name": "MyPlugin",
"Type": "Runtime",
"LoadingPhase": "Default"
},
{
"Name": "MyPluginEditor",
"Type": "Editor",
"LoadingPhase": "Default"
}
],
"Plugins": [ // 의존하는 다른 플러그인(로딩 순서보장)
{
"Name": "EnhancedInput",
"Enabled": true
}
]
}
// MyPluginModule.cpp
IMPLEMENT_MODULE(FMyPluginModule, MyPlugin)
cpp파일에 IMPLEMENT_MODULE 매크로로 모듈 등록해야함MyPlugin/
├── MyPlugin.uplugin // 플러그인 파일
├── Content/
└── Source/
├── MyPlugin/ // 모듈
│ ├── MyPlugin.Build.cs // 모듈의 build.cs 파일
│ ├── Private/
│ └── Public/
└── MyPluginEditor/ // 모듈
├── MyPluginEditor.Build.cs // 모듈의 build.cs 파일
├── Private/
└── Public/

Engine\Plugin : 모든 프로젝트에서 사용 가능 (엔진 내장)
프로젝트\Plugins : 해당 프로젝트 전용
Engine\Plugins\Marketplace : 에픽 런처로 설치한 플러그인
using UnrealBuildTool;
using System.IO;
public class MyGame : ModuleRules
{
public MyGame(ReadOnlyTargetRules Target) : base(Target)
{
// PCH 사용 방식 (보통 이대로 사용)
PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;
bEnforceIWYU = true; // 불필요한 include 시 경고 발생여부
// Public 의존성
PublicDependencyModuleNames.AddRange(new string[]
{
"Core",
"CoreUObject",
"Engine"
});
// Private 의존성
PrivateDependencyModuleNames.AddRange(new string[]
{
"Slate",
"SlateCore"
});
// 에디터 전용 의존성
if (Target.bBuildEditor)
{
PrivateDependencyModuleNames.Add("UnrealEd");
}
}
}
PCH(PreCompiledHeader)방식을 통해 자주 사용하는 헤더들을 미리 컴파일함
PublicDependencyModuleNames : 이 모듈의 Public 헤더(.h)에서 사용하는 모듈을 등록
Core, CoreUObject, UMG 등을 추가해줘야 해당 모듈들을 사용 가능.
의존성을 가지는데, A모듈이 B에 의존하게 되면, B가 의존하는 다른 모듈들에도 자동으로 의존하게 됨. 그래서 똑같은거 여러번 안 써줘도 됨
ModuleA (PublicDependency: Engine, Core)
↑
ModuleB (PublicDependency: ModuleA)
->B모듈은 자동으로 Engine, Core 의존성도 받음
PrivateDependencyModuleNames : 똑같은 의존인데, 얘는 전파가 안 됨ModuleA (PrivateDependency: Slate)
↑
ModuleB (PublicDependency: ModuleA)
->ModuleB는 Slate에 접근 불가. 직접 의존성 추가해야함
// .h (Public 폴더)
#include "GameFramework/Character.h" // Engine 모듈
#include "AbilitySystemInterface.h" // GameplayAbilities 모듈
// .cpp (Private 폴더)
#include "Components/WidgetComponent.h" // UMG 모듈
#include "NavigationSystem.h" // NavigationSystem 모듈
// Build.cs
// 헤더에서 사용하는 모듈들 추가
PublicDependencyModuleNames.AddRange(new string[]
{
"Core", "CoreUObject", "Engine",
"GameplayAbilities"
});
// cpp에서 사용하는 모듈들 추가
PrivateDependencyModuleNames.AddRange(new string[]
{
"UMG", // cpp에서만 사용
"NavigationSystem"
});
Build.cs에 의존하는 모듈 추가하지 않고 그냥 사용하면 UHT가 해당 모듈의 타입을 인식 못 해에러남
"UCLASS가 인식되지 않습니다" 에러의 원인 중 대부분을 차지
#include "Abilities/GameplayAbility.h" // 모듈 그냥 사용
#include "UMyAbility.generated.h" // 반드시 마지막!
UCLASS()
class UMyAbility : public UGameplayAbility // 부모 클래스 인식 불가!
{
GENERATED_BODY()
};
Build.cs에 의존성 추가하고, .uproject에 플러그인 활성화 필요// Build.cs
PublicDependencyModuleNames.Add("GameplayAbilities");
// .uproject
{
"Plugins": [
{ "Name": "GameplayAbilities", "Enabled": true }
]
}