icon
8장 : AI 시스템 구축

간단한 AI 의사결정 모델 구현


지금까지 우리는 비헤이비어 트리, EQS, 내비게이션, 그리고 센서 시스템이라는 AI 구축의 핵심 도구들을 개별적으로 살펴보았습니다. 이제 이 모든 요소들을 결합하여, 플레이어를 감지하고, 추적하고, 공격하거나, 플레이어를 놓치면 순찰하는 간단한 AI 의사결정 모델을 구현해보겠습니다. 이는 AI가 '인지 → 판단 → 행동'의 순환을 통해 작동하는 기본적인 패턴을 보여줄 것입니다.


AI 의사결정 모델의 목표

우리가 구현할 AI는 다음과 같은 의사결정 과정을 따릅니다.

  1. 초기 상태: 순찰(Patrol) 또는 대기(Idle)
  2. 플레이어 감지: AI Perception을 통해 플레이어를 시야 또는 청각으로 감지합니다.
  3. 추적/전투: 플레이어가 감지되면 플레이어를 추적하고, 일정 거리 내에 들어오면 공격합니다.
  4. 플레이어 놓침: 플레이어를 시야/청각에서 놓치면, 마지막으로 감지했던 위치로 이동하여 탐색합니다.
  5. 탐색 실패: 마지막 감지 위치에서도 플레이어를 찾지 못하면 다시 순찰 상태로 돌아갑니다.

시스템 구현을 위한 준비물

  • 플레이어 캐릭터: BP_PlayerCharacter (AI Perception Stimuli Source가 설정되어 있어야 함)
  • AI 폰/캐릭터: BP_EnemyCharacter (NavMesh 위에 배치될 것임)
  • AI 컨트롤러: AIC_Enemy (AI Perception Component 및 Run Behavior Tree 설정)
  • 블랙보드: BB_EnemyAI (필요한 키: TargetActor (Object), TargetLocation (Vector), IsPlayerDetected (Boolean), PatrolLocation (Vector))
  • 비헤이비어 트리: BT_EnemyAI (AI의 행동 로직)
  • 내비메시 볼륨: 레벨에 배치되어 AI가 이동할 수 있는 영역 설정

구현 단계별 가이드

이전 절에서 다룬 내용을 바탕으로 각 요소를 이미 설정했다고 가정하고, 이제 이들을 비헤이비어 트리에 결합하는 데 중점을 둡니다.

블랙보드 키 추가

BB_EnemyAI 블랙보드에 다음 키들을 추가합니다.

  • TargetActor (Object, Base Class: Actor)
  • TargetLocation (Vector)
  • IsPlayerDetected (Boolean) - AI가 플레이어를 감지했는지 여부
  • PatrolLocation (Vector) - AI가 순찰할 목표 위치

AI 컨트롤러 (AIC_Enemy) 설정

AIC_EnemyAI Perception 컴포넌트에서 On Target Perception Updated 이벤트를 처리하여 블랙보드를 업데이트합니다.

  • 플레이어 감지 시 (Successfully Sensed가 True):
    • TargetActor 키에 감지된 플레이어 액터(BP_PlayerCharacter)를 Set Blackboard Value as Object로 저장.
    • TargetLocation 키에 플레이어의 현재 위치(Get Actor Location)를 Set Blackboard Value as Vector로 저장.
    • IsPlayerDetected 키를 Set Blackboard Value as BoolTrue로 설정.
  • 플레이어 놓침 시 (Successfully Sensed가 False):
    • TargetActor 키를 Clear Blackboard Value로 지움.
    • IsPlayerDetected 키를 Set Blackboard Value as BoolFalse로 설정.
    • 중요: TargetLocation은 플레이어를 놓친 마지막 위치이므로, 당장 지우지 않고 탐색에 활용합니다.

비헤이비어 트리 (BT_EnemyAI) 구현

이제 BT_EnemyAI를 열고 다음 구조로 AI의 의사결정 모델을 만듭니다.

Root
  |
  Selector (AI의 메인 의사결정, 우선순위: 전투/탐색 > 순찰)
    |
    +--- Sequence (플레이어 추적/공격)
    |      |
    |      +--- Decorator: Blackboard Based Condition (IsPlayerDetected == True)
    |      |      (플레이어가 감지되었을 때만 이 브랜치를 실행)
    |      |
    |      +--- Task: Move To (Blackboard Key: TargetActor, Acceptable Radius: 150)
    |      |      (플레이어에게 접근)
    |      |
    |      +--- Task: Attack Player (새로운 커스텀 태스크 블루프린트)
    |      |      (공격 로직 - 애니메이션 재생, 데미지 적용 등)
    |      |
    |      +--- Service: Update Target Location (플레이어 위치를 지속적으로 TargetLocation에 업데이트)
    |             (부모인 Sequence 노드에 붙여, 해당 시퀀스가 실행되는 동안 주기적으로 실행되도록)
    |             (블랙보드 키: TargetActor에서 Get Actor Location을 가져와 TargetLocation에 저장)
    |
    +--- Sequence (플레이어 탐색)
    |      |
    |      +--- Decorator: Blackboard Based Condition (IsPlayerDetected == False AND TargetLocation != Empty)
    |      |      (플레이어를 놓쳤지만 마지막 위치 정보가 있을 때)
    |      |
    |      +--- Task: Move To (Blackboard Key: TargetLocation, Acceptable Radius: 50)
    |      |      (마지막 감지 위치로 이동)
    |      |
    |      +--- Task: Wait (3.0초 대기)
    |      |      (해당 위치에서 잠시 탐색)
    |      |
    |      +--- Task: Clear Last Known Location (새로운 커스텀 태스크 블루프린트)
    |             (탐색을 마쳤으므로 TargetLocation 키를 Clear Blackboard Value로 지움)
    |
    +--- Sequence (순찰/대기)
           |
           +--- Task: Find Patrol Location (새로운 커스텀 태스크 블루프린트)
           |      (현재 위치 주변의 랜덤한 이동 가능한 지점을 찾아 PatrolLocation에 저장)
           |      (NavSystemLib의 Get Random Reachable Point in Radius 노드 활용)
           |
           +--- Task: Move To (Blackboard Key: PatrolLocation, Acceptable Radius: 100)
           |      (순찰 지점으로 이동)
           |
           +--- Task: Wait (5.0초 대기)
                  (잠시 대기 후 다음 순찰 지점 탐색)

새로운 태스크 블루프린트 생성

위 비헤이비어 트리 구조에 필요한 커스텀 태스크를 생성합니다.

  1. BTTask_AttackPlayer (공격 태스크):

    • 콘텐츠 브라우저에서 마우스 우클릭 > 블루프린트 클래스(Blueprint Class) > All Classes에서 BTTask_BlueprintBase를 검색하여 선택합니다.
    • 그래프 탭: Receive Execute AI 이벤트를 오버라이드합니다.
    • 여기서 공격 애니메이션을 재생하고 (애님 몽타주 재생), 공격 타이밍에 Apply Damage 노드를 호출하는 등의 로직을 구현합니다.
    • 태스크 완료 시 Finish Execute 노드를 호출하고 SuccessTrue로 설정합니다.
  2. BTTask_ClearLastKnownLocation (마지막 위치 지우기 태스크)

    • BTTask_BlueprintBase를 상속받아 생성합니다.
    • 그래프 탭: Receive Execute AI 이벤트를 오버라이드합니다.
    • Get Blackboard Component 노드를 호출하여 블랙보드 참조를 얻습니다.
    • 블랙보드 참조에서 Clear Value 노드를 호출하고 Key Name 핀에 TargetLocation (키 이름)을 연결합니다.
    • Finish Execute 노드를 호출하고 SuccessTrue로 설정합니다.
  3. BTTask_FindPatrolLocation (순찰 위치 찾기 태스크)

    • BTTask_BlueprintBase를 상속받아 생성합니다.
    • 그래프 탭: Receive Execute AI 이벤트를 오버라이드합니다.
    • Get AI Controller > Get Controlled Pawn 노드를 통해 AI의 현재 위치를 얻습니다.
    • Get Random Reachable Point in Radius 노드를 호출합니다.
      • Origin은 AI의 현재 위치.
      • Radius는 순찰 반경 (예: 1000.0).
    • 찾아낸 랜덤 위치를 Get Blackboard Component 노드를 통해 Set Value as Vector 노드로 PatrolLocation 블랙보드 키에 저장합니다.
    • Finish Execute 노드를 호출하고 SuccessTrue로 설정합니다.

BTService_UpdateTargetLocation

플레이어를 추적하는 동안 플레이어의 위치를 지속적으로 업데이트하는 서비스입니다.

  1. 서비스 블루프린트 생성
    • 콘텐츠 브라우저에서 마우스 우클릭 > 블루프린트 클래스(Blueprint Class) > All Classes에서 BTService_BlueprintBase를 검색하여 선택합니다.
    • 이름을 BTS_UpdateTargetLocation으로 지정합니다.
  2. 그래프 탭
    • Receive Tick AI 이벤트를 오버라이드합니다.
    • Receive Tick AI 이벤트 노드를 선택하고 디테일 패널에서 Tick Interval0.5초 정도로 설정합니다. (너무 자주 업데이트하면 성능 저하)
    • Controlled Pawn 핀에서 Cast To Character (또는 Cast To BP_EnemyCharacter)를 연결합니다.
    • Owner Controller 핀에서 Get Blackboard Component 노드를 호출합니다.
    • Blackboard Component에서 Get Value as Object 노드를 호출하고 Key Name 핀에 TargetActor를 연결합니다.
    • Get Value as ObjectReturn Value에서 Cast To BP_PlayerCharacter를 연결합니다.
    • 캐스팅 성공 시, As BP Player Character 핀에서 Get Actor Location 노드를 호출합니다.
    • 이 위치를 Blackboard ComponentSet Value as Vector 노드를 통해 TargetLocation 블랙보드 키에 저장합니다.
    • 컴파일 및 저장합니다.

레벨 배치 및 테스트

  1. 레벨에 Nav Mesh Bounds Volume이 AI 이동 영역을 포함하도록 배치하고 P 키를 눌러 내비메시를 확인합니다.
  2. BP_EnemyCharacter를 레벨에 배치합니다.
  3. 게임을 플레이하고 AI의 행동을 관찰합니다.
    • AI가 순찰하다가 플레이어를 발견하면 추적하고 공격합니다.
    • 플레이어가 숨거나 AI의 시야/청각 반경을 벗어나면, AI는 마지막으로 플레이어를 본 위치로 이동하여 잠시 탐색합니다.
    • 탐색에도 실패하면 다시 순찰을 시작합니다.
  4. 디버깅
    • 게임 플레이 중 ~ 키를 눌러 콘솔을 열고 ai.debugdrawpath 1을 입력하여 AI의 이동 경로를 확인합니다.
    • ai.blackboard를 입력하여 AI의 블랙보드 값을 확인합니다.
    • 비헤이비어 트리 에디터에서 디버그(Debug) 드롭다운 메뉴를 통해 실행 중인 AI를 선택하고, 트리의 활성화된 노드를 실시간으로 확인합니다.

추가적인 개선 사항

이 모델은 기본적인 의사결정의 예시이며, 실제 게임에서는 더욱 복잡한 로직이 추가됩니다.

  • 다양한 공격 패턴: 근접 공격, 원거리 공격, 스킬 사용 등을 Attack Player 태스크 내부에서 또는 별도의 태스크로 분리하여 구현.
  • 회피 및 엄폐: EQS를 활용하여 엄폐 위치를 찾고 이동하는 로직 추가.
  • 피해 반응: 데미지를 입었을 때 특정 애니메이션을 재생하거나, 후퇴하는 행동 추가.
  • 그룹 AI: 여러 AI가 협동하거나 경쟁하는 로직 구현.
  • 감지 수준: 플레이어의 행동(예: 웅크리기, 빠르게 달리기)에 따라 감지될 확률이나 거리가 달라지도록 설정.

이번 절에서는 언리얼 엔진의 비헤이비어 트리, 블랙보드, AI Perception, 내비게이션 시스템을 통합하여 간단하지만 기능적인 AI 의사결정 모델을 구현하는 방법에 대해 알아보았습니다. AI가 환경을 인지하고, 판단하며, 행동하는 이 기본적인 순환은 모든 복잡한 AI 시스템의 기반이 됩니다.

이로써 8장 'AI 시스템 구축'의 모든 내용을 마쳤습니다.