Mass Entity 개요
UE5의 데이터 지향 ECS 프레임워크, Mass Entity의 탄생 배경과 핵심 철학을 이해합니다
ECS 패러다임의 이해
Entity Component System이 기존 OOP와 어떻게 다른지 살펴봅니다
전통적인 Unreal Engine 개발은 객체 지향 프로그래밍(OOP) 기반입니다. AActor, UActorComponent 등의 클래스 상속 계층 구조가 핵심이죠. 하지만 수만 개의 엔티티를 동시에 시뮬레이션해야 할 때, 이 방식은 심각한 성능 병목을 유발합니다.
Entity는 고유 ID, Component는 순수 데이터, System은 로직을 담당합니다. 데이터와 로직을 완전히 분리하여 캐시 친화적인 배치 처리를 가능하게 합니다.
| 비교 항목 | 전통 OOP (Actor 기반) | ECS (Mass Entity) |
|---|---|---|
| 데이터 저장 | 객체 내부에 분산 (AoS) | 동일 타입 연속 배치 (SoA) |
| 로직 위치 | 클래스 메서드 (Tick) | 별도 Processor (System) |
| 캐시 효율 | 낮음 (포인터 추적) | 높음 (연속 메모리) |
| 10,000개 엔티티 | 심각한 성능 저하 | 효율적 배치 처리 |
| 확장성 | 상속 계층에 의존 | 런타임 조합(Composition) |
Mass Entity에서 UE5의 ECS 용어는 다음과 같이 매핑됩니다:
// ECS 일반 용어 → UE5 Mass Entity 용어
// ─────────────────────────────────────────────
Entity → FMassEntityHandle
Component (데이터) → FMassFragment
Tag (마커) → FMassTag
System (로직) → UMassProcessor
Archetype (조합) → FMassArchetypeHandle
World (관리자) → FMassEntityManager
데이터 지향 설계 (DOD)
Mass Entity의 성능이 뛰어난 근본적인 이유를 이해합니다
데이터 지향 설계(Data-Oriented Design, DOD)는 CPU 캐시 활용을 극대화하는 설계 철학입니다. 현대 CPU에서 메모리 접근은 연산보다 수십~수백 배 느리기 때문에, 데이터 배치 방식이 성능을 결정합니다.
AoS vs SoA 메모리 레이아웃
// Actor 기반: 각 객체가 모든 데이터를 포함
// 메모리: [Pos1|Vel1|HP1|...] [Pos2|Vel2|HP2|...] [Pos3|Vel3|HP3|...]
// ↑ 캐시라인에 불필요한 데이터가 함께 로드됨
class AMyActor : public AActor
{
FVector Position; // 12 bytes
FVector Velocity; // 12 bytes
float Health; // 4 bytes
USkeletalMesh* Mesh; // 8 bytes
// ... 수백 바이트의 AActor 오버헤드
};
// Mass Entity: 같은 타입의 데이터가 연속 배치
// 메모리: [Pos1|Pos2|Pos3|...] [Vel1|Vel2|Vel3|...] [HP1|HP2|HP3|...]
// ↑ 캐시라인에 필요한 데이터만 연속 로드
// 각 Fragment는 독립적인 데이터 단위
USTRUCT()
struct FTransformFragment : public FMassFragment
{
GENERATED_BODY()
FTransform Transform; // 48 bytes만 연속 저장
};
USTRUCT()
struct FVelocityFragment : public FMassFragment
{
GENERATED_BODY()
FVector Value; // 12 bytes만 연속 저장
};
City Sample 프로젝트에서 Mass Entity는 30,000개 이상의 차량과 보행자를 단일 프레임 내에서 시뮬레이션합니다. 동일한 규모를 Actor 기반으로 처리하면 프레임 드롭이 불가피합니다.
Mass Framework 모듈 구조
Mass 프레임워크를 구성하는 플러그인과 모듈의 전체 그림을 파악합니다
Mass Entity는 단일 플러그인이 아닌 여러 모듈의 집합체입니다. 각 모듈은 독립적으로 활성화할 수 있으며, 필요에 따라 조합하여 사용합니다.
// ┌─────────────────────────────────────────────────┐
// │ Mass Framework 전체 구조 │
// ├─────────────────────────────────────────────────┤
// │ │
// │ ┌─── 핵심 계층 ───────────────────────────┐ │
// │ │ MassEntity (Core) │ │
// │ │ - FMassEntityManager │ │
// │ │ - Fragment, Tag, Archetype, Chunk │ │
// │ │ - Processor, Query, Observer │ │
// │ └──────────────────────────────────────────┘ │
// │ ↑ │
// │ ┌─── 게임플레이 계층 ─────────────────────┐ │
// │ │ MassGameplay │ │
// │ │ - MassSpawner, MassRepresentation │ │
// │ │ - MassLOD, MassSignals │ │
// │ │ - MassMovement, MassActors │ │
// │ │ - MassReplication, MassSmartObjects │ │
// │ └──────────────────────────────────────────┘ │
// │ ↑ │
// │ ┌─── AI 계층 ─────────────────────────────┐ │
// │ │ MassAI │ │
// │ │ - StateTree 통합 │ │
// │ │ - MassNavigation, MassZoneGraph │ │
// │ │ - MassAvoidance │ │
// │ └──────────────────────────────────────────┘ │
// │ │
// └─────────────────────────────────────────────────┘
| 모듈 | 역할 | 핵심 클래스 |
|---|---|---|
| MassEntity | 핵심 ECS 프레임워크 | FMassEntityManager, UMassProcessor |
| MassSpawner | 엔티티 생성/관리 | AMassSpawner, UMassSpawnerSubsystem |
| MassRepresentation | 시각적 표현 | UMassRepresentationSubsystem |
| MassLOD | LOD 계산 | UMassLODSubsystem |
| MassMovement | 이동 시뮬레이션 | FMassVelocityFragment |
| MassSignals | 이벤트 시그널 | UMassSignalSubsystem |
| MassNavigation | 경로 탐색 | FMassNavigationFragment |
| MassAI | AI 행동/StateTree | UMassStateTreeSubsystem |
Mass Entity 관련 플러그인들은 기본적으로 비활성화되어 있습니다. Edit > Plugins에서 MassEntity, MassGameplay, MassAI 플러그인을 활성화해야 합니다. 또한 .Build.cs 파일에 해당 모듈 의존성을 추가해야 합니다.
시뮬레이션 인스턴스
Mass Entity 시뮬레이션의 실행 구조와 생명주기를 이해합니다
Mass Entity 시뮬레이션은 두 가지 핵심 컴포넌트로 구성됩니다:
FMassEntityManager
모든 엔티티 데이터의 컨테이너입니다. Archetype을 생성하고 관리하며, 엔티티의 구성(Composition) 변경을 처리합니다.
FMassProcessingPhaseManager
매 틱마다 6개의 처리 단계를 순서대로 실행합니다. 각 단계에 등록된 Processor들이 엔티티 데이터를 처리합니다.
시뮬레이션 인스턴스 종류 (UE 5.5+)
| 인스턴스 | 월드 타입 | 특징 |
|---|---|---|
| UMassSimulationSubsystem | Editor World | Realtime 뷰포트 모드에서만 틱 |
| UMassSimulationSubsystem | Game/PIE World | 런타임 시뮬레이션, 자동 생성/파괴 |
| UMassEntityEditorSubsystem | Editor Only | 에디터 전용 기능, 월드 독립 |
// 월드에서 EntityManager에 접근하는 방법
void MyFunction(UWorld* World)
{
// MassEntitySubsystem을 통해 접근
UMassEntitySubsystem* EntitySubsystem =
World->GetSubsystem<UMassEntitySubsystem>();
FMassEntityManager& EntityManager =
EntitySubsystem->GetMutableEntityManager();
// 또는 SimulationSubsystem을 통해 접근
UMassSimulationSubsystem* SimSubsystem =
World->GetSubsystem<UMassSimulationSubsystem>();
}
Mass Entity를 사용하려면 프로젝트의 .Build.cs에 다음 모듈을 추가하세요:
PublicDependencyModuleNames.AddRange(new string[]
{
"MassEntity",
"MassCommon",
"MassSpawner",
"MassGameplayDebug",
"StructUtils",
// 필요 시 추가
"MassMovement",
"MassRepresentation",
"MassLOD",
"MassSignals",
"MassNavigation",
"MassAI",
});
핵심 요약
- Mass Entity는 UE5의 데이터 지향 ECS 프레임워크로, 대규모 엔티티 시뮬레이션에 최적화되어 있다
- ECS 패러다임에서 Entity = ID, Fragment = 데이터(Component), Processor = 로직(System)이다
- SoA(Structure of Arrays) 메모리 레이아웃으로 캐시 효율을 극대화하며, 이것이 성능 차이의 핵심이다
- Mass Framework는 MassEntity(핵심), MassGameplay(게임플레이), MassAI(AI)의 계층 구조로 이루어져 있다
- 시뮬레이션은 FMassEntityManager(데이터 저장)와 FMassProcessingPhaseManager(로직 실행)로 구동된다
- 실험적(Experimental) 상태이지만, City Sample 등 Epic의 대규모 프로젝트에서 실전 활용 중이다
도전 과제
배운 내용을 직접 실습해보세요
Edit > Plugins에서 MassEntity, MassGameplay 플러그인을 활성화하고, .Build.cs에 MassEntity, MassCommon, StructUtils 모듈 의존성을 추가하세요. 컴파일 성공을 확인한 뒤 간단한 FMassFragment 구조체를 선언하세요.
동일한 동작(위치 이동)을 AActor 1000개와 Mass Entity 1000개로 각각 구현하세요. stat unit 명령으로 Game Thread 시간을 비교하고, 10000개로 늘렸을 때의 차이를 측정하세요.
Epic Games의 City Sample 프로젝트를 다운로드하여 Mass Entity 관련 코드를 분석하세요. FMassTrafficVehicleSimulationFragment 등의 Fragment 구조와 Processor 실행 흐름을 추적하세요.