PART 6 · 강의 1/3

대규모 시뮬레이션

City Sample을 분석하고, 군중 및 교통 시뮬레이션을 구현하는 방법을 학습합니다

01

City Sample 분석

Epic Games의 대규모 시뮬레이션 레퍼런스

City Sample은 Epic Games가 Mass Entity의 실전 활용을 보여주기 위해 제작한 프로젝트입니다. 수만 대의 차량과 보행자가 도시 환경에서 실시간으로 시뮬레이션됩니다.

항목 City Sample 스펙
보행자 수 ~15,000+
차량 수 ~15,000+
동시 Actor (근접) ~50~100개
ISM 표현 나머지 전부
내비게이션 ZoneGraph (레인 기반)
AI 행동 StateTree + SmartObject
목표 FPS 30~60 FPS (하드웨어 의존)
City Sample 아키텍처 개요 // City Sample의 Mass Entity 구성 // // ┌── 보행자 시스템 ─────────────────────────┐ // │ Config: DA_Pedestrian │ // │ - StateTree: 배회, 횡단보도, SmartObject │ // │ - Navigation: ZoneGraph (인도 레인) │ // │ - Avoidance: Force 기반 (보행자 간) │ // │ - Representation: Skeletal → ISM (VAT) │ // │ - SmartObject: 벤치 앉기, 대기 등 │ // └────────────────────────────────────────────┘ // // ┌── 차량 시스템 ──────────────────────────────┐ // │ Config: DA_Vehicle │ // │ - StateTree: 도로 주행, 신호 대기 │ // │ - Navigation: ZoneGraph (도로 레인) │ // │ - Avoidance: 차간 거리 유지 │ // │ - Representation: Vehicle Actor → ISM │ // │ - Traffic: 교통 신호 시스템 연동 │ // └──────────────────────────────────────────────┘
02

군중 시뮬레이션 설계

대규모 군중을 구현하기 위한 설계 전략

군중 시뮬레이션 체크리스트 // 1. 엔티티 정의 // ☐ 보행자 타입별 Config (시민, 경찰, 상인 등) // ☐ SharedFragment로 타입별 설정 공유 // ☐ Tag로 상태 분류 (활동중, 대기중, 이동중) // // 2. 행동 시스템 // ☐ StateTree로 행동 패턴 정의 // ☐ SmartObject로 환경 상호작용 // ☐ Signal로 이벤트 반응 (경보, 위험 등) // // 3. 이동 시스템 // ☐ ZoneGraph로 이동 경로 정의 // ☐ Avoidance로 군중 흐름 유지 // ☐ 이동 속도 다양성 (SharedFragment) // // 4. 시각화 시스템 // ☐ 근접: Skeletal Mesh Actor // ☐ 원거리: ISM + VAT // ☐ Actor Pool 크기 결정 // ☐ LOD 거리 설정 // // 5. 최적화 // ☐ Simulation LOD로 연산 절감 // ☐ Archetype 파편화 최소화 // ☐ Fragment 크기 최적화
점진적 구축 전략

Step 1: 1,000개의 정적 ISM 엔티티 배치
Step 2: 간단한 이동 Processor 추가
Step 3: Avoidance 추가
Step 4: StateTree AI 추가
Step 5: Actor 전환 및 LOD 추가
Step 6: 10,000개로 스케일업 및 최적화

03

교통 시뮬레이션

차량 시뮬레이션의 구현 전략

교통 시뮬레이션 구성 요소 // 차량 시뮬레이션 Fragment 구성 USTRUCT() struct FVehicleLaneFragment : public FMassFragment { GENERATED_BODY() int32 CurrentLaneIndex; // 현재 도로 레인 float LaneProgress; // 레인 내 진행도 (0~1) float DesiredSpeed; // 목표 속도 }; USTRUCT() struct FTrafficSignalFragment : public FMassFragment { GENERATED_BODY() bool bShouldStop; // 정지 신호 float DistanceToSignal; // 다음 신호까지 거리 }; USTRUCT() struct FFollowDistanceFragment : public FMassFragment { GENERATED_BODY() float DistanceToFrontVehicle; // 앞 차와의 거리 float SafeDistance; // 안전 거리 };
레인 기반 이동의 장점

차량은 자유 경로가 아닌 레인(Lane)을 따라 이동합니다. 복잡한 경로 탐색이 필요 없어 연산이 빠르고, 교차로에서의 우선순위 처리, 차선 변경 등을 체계적으로 구현할 수 있습니다.

04

Mass Signal 활용 패턴

대규모 시뮬레이션에서의 이벤트 처리

C++ - 실전 Signal 패턴들 // 범위 기반 Signal 전송: 폭발 반경 내 모든 엔티티에 알림 void BroadcastExplosion( UWorld* World, FVector Origin, float Radius) { FMassEntityManager& EM = UMassEntitySubsystem::GetEntityManager(World); UMassSignalSubsystem* Signals = World->GetSubsystem<UMassSignalSubsystem>(); // 범위 내 엔티티 수집 TArray<FMassEntityHandle> NearbyEntities; // ... 공간 쿼리로 범위 내 엔티티 수집 ... // Signal 전송 Signals->SignalEntities( TEXT("Explosion"), NearbyEntities); } // 글로벌 Signal: 모든 엔티티에 영향 // 예: 비 시작, 야간 전환, 경보 발령 Signals->SignalEntities( TEXT("GlobalAlert"), AllCivilianEntities); // 체인 Signal: 하나의 Signal이 다른 Signal을 트리거 // 좀비 감염 → 주변에 "ZombieNearby" Signal 전파 // → 시민이 "Flee" 상태로 전환 // → 도망치는 시민이 다른 시민에게 "Panic" Signal 전파
SUMMARY

핵심 요약

  • City Sample은 Mass Entity로 30,000+ 보행자/차량을 시뮬레이션하는 Epic의 레퍼런스 프로젝트이다
  • 군중 시뮬레이션은 엔티티 정의, 행동 시스템, 이동, 시각화, 최적화의 5단계로 구축한다
  • 교통 시뮬레이션은 ZoneGraph 레인 기반으로 구현하며, 교통 신호와 차간 거리 Fragment를 사용한다
  • Mass Signal은 범위 기반, 글로벌, 체인 패턴으로 대규모 이벤트를 효율적으로 처리한다
  • 점진적 구축 전략으로 복잡도를 관리하며, 각 단계에서 성능을 검증한다
  • SharedFragment로 엔티티 타입별 설정을 공유하여 메모리와 Archetype 효율을 유지한다
PRACTICE

도전 과제

배운 내용을 직접 실습해보세요

실습 1: 10,000개 엔티티 시뮬레이션

MassSpawner로 10,000개의 엔티티를 스폰하고, 간단한 이동 Processor를 적용하세요. stat unit, stat MassEntity로 프레임 시간을 측정하고, 목표 프레임레이트(60fps)를 달성하는지 확인하세요.

실습 2: 멀티스레드 Processor 활용

동일 Processor를 bRequiresGameThreadExecution=true/false로 전환하며 성능을 비교하세요. 멀티스레드로 전환 시 Thread Safety를 보장하기 위한 코드 패턴(Atomic, Local Buffer 등)을 적용하세요.

심화 과제: 50,000개 엔티티 실전 시뮬레이션

50,000개의 엔티티로 도시 시뮬레이션을 구현하세요: 보행자(Navigation + Avoidance), 차량(Lane Following), 환경 객체(Static)를 모두 포함하고, LOD와 Scalability로 60fps를 유지하세요.