콘텐츠로 이동

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

9. 플레이어 차량과 Mass Traffic 상호작용

섹션 제목: “9. 플레이어 차량과 Mass Traffic 상호작용”

플레이어 차량은 Mass Entity가 아니지만 트래픽 차량이 플레이어를 인식하고 회피하게 만들 수 있습니다.

// 플레이어 위치를 Mass Traffic 회피 시스템에 등록
// MassAvoidance는 "장애물 소스" 인터페이스를 통해 외부 오브젝트를 수용합니다
UCLASS()
class APlayerVehicle : public APawn
{
GENERATED_BODY()
UPROPERTY(VisibleAnywhere)
UMassObstacleComponent* ObstacleComp; // Mass Traffic 회피 대상으로 등록
public:
APlayerVehicle()
{
// MassObstacleComponent가 이 액터를 ZoneGraph 장애물로 자동 등록
ObstacleComp = CreateDefaultSubobject<UMassObstacleComponent>(
TEXT("MassObstacle"));
}
};
// 레인 예약 — 플레이어가 특정 레인 점유 시 트래픽 차량 우회
void APlayerVehicle::OnEnterLane(int32 LaneIndex)
{
if (auto* TrafficSubsystem = GetWorld()->GetSubsystem<UMassTrafficSubsystem>())
{
TrafficSubsystem->SetLaneRestriction(
LaneIndex, EMassTrafficLaneRestriction::BlockedByPlayer);
}
}

주의 사항:

  • UMassObstacleComponentMassTraffic 플러그인에 포함 (City Sample 기준)
  • 플레이어 차량 반경을 AvoidanceRadius 프로퍼티로 설정
  • 플레이어가 역주행 시 lane direction 필터로 트래픽 분리 필요

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