PART 4 - 강의 1/3

EQS 기초와 Generator

Environment Query System의 개념, EnvQuery 에셋, 주요 Generator 종류를 학습합니다

01

EQS(Environment Query System) 개요

AI의 공간 인지 시스템

EQS는 AI가 환경을 분석하여 최적의 위치나 액터를 선택하는 시스템입니다. "어디로 이동할까?", "어디에 엄폐할까?", "어떤 적을 공격할까?" 같은 공간적 의사결정을 체계적으로 해결합니다.

EQS 실행 흐름
Generator (후보 생성) Test (점수 매기기) Scoring (순위 결정) Best Item 선택
C++// EQS 활성화 (Project Settings에서) // Engine - AI - Environment Querying System: Enabled // EnvQuery 에셋 구조 // UEnvQuery // ├── Generator: 후보 아이템 생성 // ├── Test 1: 후보에 점수 부여 // ├── Test 2: 추가 점수 부여 // └── ... // BT에서 EQS 실행 // BTTask_RunEQSQuery 사용 // 또는 C++에서 직접 실행: UEnvQueryManager* EQSManager = UEnvQueryManager::GetCurrent(GetWorld()); FEnvQueryRequest Request(EQSQueryAsset, this); Request.Execute( EEnvQueryRunMode::SingleBestItem, // 최고 점수 1개 FQueryFinishedSignature::CreateUObject( this, &AMyAIController::OnEQSQueryFinished)); void AMyAIController::OnEQSQueryFinished( TSharedPtr<FEnvQueryResult> Result) { if (Result->IsSuccessful()) { FVector BestLocation = Result->GetItemAsLocation(0); // 또는 AActor* BestActor = Result->GetItemAsActor(0); } } // RunMode 옵션 // SingleBestItem: 최고 점수 아이템 1개 // RandomBest5Pct: 상위 5% 중 랜덤 선택 // RandomBest25Pct: 상위 25% 중 랜덤 선택 // AllMatching: 필터 통과한 모든 아이템

RandomBest25Pct를 사용하면 매번 같은 위치를 선택하는 것을 방지하면서도 합리적인 위치를 선택합니다. 순찰 포인트 선택 등에 적합합니다.

02

SimpleGrid Generator

격자 기반 후보 위치 생성

UEnvQueryGenerator_SimpleGrid는 가장 많이 사용되는 Generator로, 지정된 Context 주변에 격자 형태로 후보 위치를 생성합니다. NavMesh 투영으로 이동 가능한 위치만 필터링할 수 있습니다.

C++// SimpleGrid Generator 주요 프로퍼티 // GridSize: 격자 한 변의 길이 (절반) // 예: GridSize=1000 → 2000x2000 영역 // SpaceBetween: 격자 간격 // 예: SpaceBetween=200 → 200cm 간격으로 점 생성 // GenerateAround: 기준 Context // 예: Querier(AI), EnemyActor, CustomContext 등 // 생성되는 아이템 수 계산: // (GridSize*2 / SpaceBetween + 1) ^ 2 // 예: 1000*2/200+1 = 11 → 11*11 = 121개 아이템 // NavMesh 투영 설정 // ProjectDown: 아래로 투영 거리 // ProjectUp: 위로 투영 거리 // PostProjectionVerticalOffset: 투영 후 오프셋 // NavigationFilter: NavArea 필터 // C++에서 커스텀 Generator 생성 UCLASS() class UEnvQueryGenerator_DefensivePositions : public UEnvQueryGenerator_SimpleGrid { GENERATED_BODY() public: UEnvQueryGenerator_DefensivePositions() { GridConfig.GridSize = FAIDataProviderFloatValue(1500.f); GridConfig.SpaceBetween = FAIDataProviderFloatValue(200.f); } };
주의

격자 간격(SpaceBetween)을 너무 작게 설정하면 후보 수가 급증합니다. GridSize=2000, SpaceBetween=100이면 1,681개 아이템이 생성되어 성능에 큰 영향을 줍니다.

03

OnCircle Generator

원형 배치 후보 생성

UEnvQueryGenerator_OnCircle는 Context 주변 원형으로 후보를 배치합니다. 측면 공격 위치, 포위 위치, 순찰 경로 등에 적합합니다. 호(Arc) 제한으로 반원이나 부채꼴 배치도 가능합니다.

C++// OnCircle Generator 주요 프로퍼티 // CircleRadius: 원의 반지름 // SpaceBetween: 점 사이 호 길이 (또는 NumberOfPoints) // ArcDirection: 호 방향 기준 // - FrontOfQuerier: AI 전방 기준 // - FrontOfContext: Context 전방 기준 // ArcAngle: 호 각도 (360 = 전체 원, 180 = 반원) // CircleCenter: 원 중심 Context // 활용 예시 1: 적 주변 포위 위치 // CircleCenter: EnemyActor // CircleRadius: 500 // SpaceBetween: 100 // ArcAngle: 360 (전체 원) // 활용 예시 2: 적 후방 측면 공격 위치 // CircleCenter: EnemyActor // CircleRadius: 600 // ArcDirection: FrontOfContext (적 전방) // ArcAngle: 180 (적 뒤쪽 반원) // 활용 예시 3: AI 전방 수색 위치 // CircleCenter: Querier // CircleRadius: 1000 // ArcDirection: FrontOfQuerier // ArcAngle: 120 (전방 120도) // 블루프린트에서 설정: // EQS 에디터 → Generator 추가 → Points: On Circle // 프로퍼티에서 반지름, 간격, Arc 설정

OnCircle의 ArcAngle을 180도로 설정하고 ArcDirection을 적의 전방으로 하면, 적의 뒤쪽 반원에서만 위치를 생성합니다. 측면 공격(Flanking) 구현에 핵심적입니다.

04

ActorsOfClass와 커스텀 Generator

액터 기반 후보 생성과 확장

UEnvQueryGenerator_ActorsOfClass는 특정 클래스의 액터들을 후보로 사용합니다. 엄폐물, 아이템, 웨이포인트 등 미리 배치된 오브젝트를 대상으로 쿼리할 때 사용합니다.

C++// ActorsOfClass Generator // SearchedActorClass: 검색할 액터 클래스 // GenerateOnlyActorsInRadius: 범위 제한 // SearchRadius: 검색 반경 // SearchCenter: 검색 기준 Context // 활용: 범위 내 CoverPoint 검색 // SearchedActorClass: ACoverPoint // SearchRadius: 2000 // SearchCenter: Querier // 커스텀 Generator 제작 UCLASS() class UEnvQueryGenerator_CoverPoints : public UEnvQueryGenerator { GENERATED_BODY() public: virtual void GenerateItems( FEnvQueryInstance& QueryInstance) const override { // Context 가져오기 TArray<FVector> ContextLocations; QueryInstance.PrepareContext( GenerateAround, ContextLocations); // 커스텀 로직으로 후보 생성 UWorld* World = GEngine->GetWorldFromContextObject( QueryInstance.Owner.Get(), EGetWorldErrorMode::LogAndReturnNull); for (const FVector& Center : ContextLocations) { // 주변 CoverPoint 검색 TArray<ACoverPoint*> CoverPoints; FindCoverPointsNear(World, Center, SearchRadius, CoverPoints); for (ACoverPoint* Cover : CoverPoints) { // EQS 아이템으로 추가 QueryInstance.AddItemData< UEnvQueryItemType_Actor>(Cover); } } } protected: UPROPERTY(EditAnywhere) TSubclassOf<UEnvQueryContext> GenerateAround; UPROPERTY(EditAnywhere) float SearchRadius = 2000.f; };
참고

커스텀 Generator에서 AddItemData<UEnvQueryItemType_Point>는 위치 아이템을, AddItemData<UEnvQueryItemType_Actor>는 액터 아이템을 추가합니다. Test에서 사용하는 ItemType이 달라지므로 주의하세요.

SUMMARY

핵심 요약

  • EQS는 Generator로 후보를 생성하고 Test로 점수를 매겨 최적의 위치/액터를 선택하는 시스템이다
  • SimpleGrid는 격자 기반, OnCircle은 원형 배치, ActorsOfClass는 기존 액터 기반 Generator이다
  • RunMode(SingleBestItem, RandomBest25Pct 등)로 결과 선택 방식을 제어한다
  • 후보 수가 성능에 직접 영향을 미치므로 GridSize와 SpaceBetween 균형이 중요하다
PRACTICE

도전 과제

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

실습 1: 기본 EQS 쿼리 생성

EQS 에디터에서 Points: Grid Generator를 배치하고, Distance Test로 플레이어와의 거리를 평가하는 쿼리를 만드세요. BT의 Run EQS Query 태스크에서 실행하여 최적 위치를 확인합니다.

실습 2: Generator 비교

SimpleGrid, Donut, OnCircle, ActorsOfClass Generator를 각각 사용한 쿼리를 만들어 디버그 시각화(EQS Testing Pawn)로 생성되는 포인트 분포를 비교하세요.

심화 과제

UEnvQueryGenerator를 상속하여 NavMesh 위의 랜덤 도달 가능 포인트를 생성하는 커스텀 Generator를 구현하세요. NavigationSystem의 GetRandomReachablePointInRadius를 활용합니다.