콘텐츠로 이동

UE5 Mass Traffic & Crowd 시뮬레이션

Mass Traffic과 Mass Crowd는 UE5 City Sample 프로젝트에서 공개된 대규모 교통/군중 시뮬레이션 플러그인입니다. Mass Entity 프레임워크 위에서 동작하며 수천 대의 차량과 군중을 실시간으로 처리합니다.


Edit → Plugins:
✓ Mass Entity
✓ Mass Gameplay
✓ MassTraffic
✓ MassCrowd
✓ ZoneGraph
✓ MassRepresentation

ZoneGraph는 차량/군중의 이동 경로를 정의하는 데이터 구조입니다.

레벨에 ZoneGraphData 액터 배치
→ Spline으로 도로/보도 경로 정의
→ Lane 태그 설정:
- Vehicle (차량 전용)
- Pedestrian (보행자 전용)
- Direction: OneWay / TwoWay
// C++에서 ZoneGraph 레인 쿼리
#include "ZoneGraphSubsystem.h"
void AMyActor::QueryNearbyLanes()
{
auto* ZoneGraphSubsystem = World->GetSubsystem<UZoneGraphSubsystem>();
FZoneGraphLaneLocation NearestLane;
float DistanceSq;
if (ZoneGraphSubsystem->FindNearestLane(
GetActorLocation(),
FZoneGraphTagFilter(), // 모든 레인
NearestLane,
DistanceSq))
{
UE_LOG(LogTemp, Log, TEXT("가까운 레인 발견: 거리 %.1f"),
FMath::Sqrt(DistanceSq));
}
}

// MassTrafficSettings 데이터 에셋 설정
UCLASS()
class UMassTrafficSettings : public UDataAsset
{
GENERATED_BODY()
public:
// 차량 속도
UPROPERTY(EditAnywhere)
float MaxSpeed = 1200.0f; // cm/s (약 43km/h)
UPROPERTY(EditAnywhere)
float MinFollowDistance = 300.0f; // 앞 차와 최소 거리
// LOD 설정
UPROPERTY(EditAnywhere)
float HighDetailDistance = 5000.0f; // 완전 시뮬레이션 범위
UPROPERTY(EditAnywhere)
float LowDetailDistance = 20000.0f; // 간소화 시뮬레이션 범위
};

// 신호등 Fragment
USTRUCT()
struct FMassTrafficLightFragment : public FMassFragment
{
GENERATED_BODY()
UPROPERTY()
ETrafficLightState State = ETrafficLightState::Green;
UPROPERTY()
float Timer = 0.0f;
UPROPERTY()
float GreenDuration = 30.0f;
float YellowDuration = 5.0f;
float RedDuration = 25.0f;
};
// 신호등 Processor
UCLASS()
class UMassTrafficLightProcessor : public UMassProcessor
{
GENERATED_BODY()
protected:
virtual void Execute(FMassEntityManager& EntityManager,
FMassExecutionContext& Context) override
{
float DeltaTime = Context.GetDeltaTimeSeconds();
EntityQuery.ForEachEntityChunk(EntityManager, Context,
[DeltaTime](FMassExecutionContext& Ctx)
{
auto Lights = Ctx.GetMutableFragmentView<FMassTrafficLightFragment>();
for (auto& Light : Lights)
{
Light.Timer += DeltaTime;
switch (Light.State)
{
case ETrafficLightState::Green:
if (Light.Timer >= Light.GreenDuration)
{ Light.State = ETrafficLightState::Yellow; Light.Timer = 0; }
break;
case ETrafficLightState::Yellow:
if (Light.Timer >= Light.YellowDuration)
{ Light.State = ETrafficLightState::Red; Light.Timer = 0; }
break;
case ETrafficLightState::Red:
if (Light.Timer >= Light.RedDuration)
{ Light.State = ETrafficLightState::Green; Light.Timer = 0; }
break;
}
}
});
}
};

// 군중 에이전트 Trait
UCLASS()
class UPedestrianTrait : public UMassEntityTraitBase
{
GENERATED_BODY()
public:
UPROPERTY(EditAnywhere)
float WalkSpeed = 140.0f; // cm/s
UPROPERTY(EditAnywhere)
float AvoidanceRadius = 50.0f;
virtual void BuildTemplate(
FMassEntityTemplateBuildContext& BuildContext,
const UWorld& World) const override
{
BuildContext.AddFragment<FMassVelocityFragment>();
BuildContext.AddFragment<FTransformFragment>();
BuildContext.AddFragment<FMassAvoidanceFragment>();
BuildContext.AddFragment<FMassZoneGraphLaneLocationFragment>();
}
};

거리별 표현:
0 ~ 5000cm → 완전 스킨 메시 (애니메이션 포함)
5000 ~ 15000cm → ISM (Instanced Static Mesh, 정적)
15000cm+ → 시뮬레이션만 (렌더링 없음)
// MassRepresentationSubsystem이 자동으로 LOD 전환 처리
// MassVisualizationLODProcessor가 거리 기반 전환

콘솔 명령:
mass.Debug.Traffic 1 — 차량 디버그 시각화
mass.Debug.Crowd 1 — 군중 디버그 시각화
mass.ProcessorTimings 1 — Processor 실행 시간 측정
zonegraph.Debug.Draw 1 — 레인 구조 시각화

항목City Sample 수치
동시 차량 수최대 18,000대
동시 군중 수최대 35,000명
프레임 유지30fps (PS5/XSX)
처리 방식Mass Entity + Niagara

Mass Traffic/Crowd는 ZoneGraph로 이동 경로를 정의하고, Mass Entity Processor로 배치 시뮬레이션하며, LOD 기반 ISM으로 렌더링 비용을 최소화하는 3단 구조입니다. City Sample 소스를 분석하면서 Traffic Light, 회피 알고리즘, 군중 행동 규칙을 게임에 맞게 커스터마이징하는 것이 효과적인 도입 방법입니다.