본문 바로가기

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

센서·블랙보드·비헤이비어 트리·내비게이션을 연결해 순찰·감지·추적·공격·탐색 순환을 구현합니다.

이 장에서 비헤이비어 트리, EQS, 내비게이션, 센서 시스템을 하나씩 만들어 봤습니다. 하지만 도구를 따로 갖춘 것만으로는 적이 순찰하다가 플레이어를 발견하고, 쫓아가 공격하고, 놓치면 마지막 위치를 살핀 뒤 다시 순찰로 돌아가는 흐름이 저절로 생기지 않습니다. 감지한 정보를 언제 블랙보드에 쓰고, 트리의 어느 가지가 그 값을 보고 행동을 바꾸는지를 하나의 규칙으로 엮어야 합니다.

이 글에서는 지금까지 만든 요소를 결합해, 인지에서 판단, 행동으로 이어지는 순환을 가진 간단한 AI 의사결정 모델을 만듭니다. 블랙보드 키와 감지 규칙을 정하고, 세 가지 우선순위의 가지로 비헤이비어 트리를 구성한 뒤, 필요한 태스크와 서비스를 블루프린트로 만들고, 조건이 바뀔 때 진행 중인 행동을 중단하는 방법까지 확인합니다.


만들 AI의 행동 순환

이 글의 AI는 다음과 같은 흐름으로 판단합니다. 처음에는 순찰하거나 대기합니다. AI Perception으로 플레이어를 눈으로 확인하거나, 소리를 들어 마지막 소음 위치를 얻으면 행동이 바뀝니다. 지금 보이는 플레이어가 있으면 쫓아가 공격하며, 공격하는 순간에도 대상과 거리, 공격 가능 조건을 다시 확인합니다. 소리만 들었다면 그 소리가 난 위치를 조사합니다.

플레이어를 시야에서 놓치면 마지막으로 확인한 위치를 탐색합니다. 청각 감지도 조사할 위치를 주지만, 그것을 플레이어가 지금 보인다는 뜻으로 다루지는 않습니다. 마지막 위치에서도 플레이어를 찾지 못하면 다시 순찰로 돌아갑니다.

이 흐름을 만들려면 다음이 준비되어 있어야 합니다. 앞의 글들에서 하나씩 설정한 것들이며, 이 글은 이미 설정했다고 가정하고 이들을 비헤이비어 트리에 결합하는 데 집중합니다.

  • 플레이어 캐릭터 BP_PlayerCharacter: AIPerceptionStimuliSource 컴포넌트가 설정되어 있어야 합니다.
  • AI 캐릭터 BP_EnemyCharacter: 내비메시 위에 배치합니다.
  • AI 컨트롤러 AIC_Enemy: AI Perception Component와 Run Behavior Tree가 설정되어 있어야 합니다.
  • 블랙보드 BB_EnemyAI와 비헤이비어 트리 BT_EnemyAI
  • 레벨의 내비메시 볼륨: AI가 이동할 영역을 감싸야 합니다.

블랙보드 키와 감지 규칙

BB_EnemyAI에 다음 네 키를 준비합니다.

키타입뜻
TargetActorObject(Base Class: Actor)지금 보이는 플레이어
TargetLocationVector조사할 위치. 마지막 확인 위치나 소음 위치
IsPlayerDetectedBoolean이 실습에서는 지금 시각으로 확인했는지 여부
PatrolLocationVector순찰할 목표 위치

다음으로 AIC_Enemy의 AI Perception에서 On Target Perception Updated를 처리해 이 키들을 갱신합니다. 이 예제는 플레이어 한 명을 대상으로 하며, 이벤트의 Actor가 플레이어인지 확인한 뒤 자극의 감각 종류를 나누어 처리합니다. 값은 초기화된 블랙보드 컴포넌트의 Set Value as Object, Set Value as Vector, Set Value as Bool과 Clear Value로 바꿉니다.

시각 감지에 성공하면 TargetActor에 플레이어를, TargetLocation에 확인한 위치를 저장하고 IsPlayerDetected를 true로 둡니다. 시각을 잃었고 그 대상이 현재 타깃이라면 IsPlayerDetected를 false로 바꾸고 TargetActor를 비우되, 이미 저장된 TargetLocation은 그대로 둡니다. 이 위치가 다음에 탐색할 마지막 확인 위치가 됩니다.

청각 감지에 성공하면 지금 시각 타깃이 없을 때만 Stimulus Location을 TargetLocation에 저장합니다. 이때 IsPlayerDetected를 true로 바꾸거나 보이지 않는 액터의 현재 위치를 읽지 않습니다. 청각 감지가 실패하거나 소음 기억이 만료되어도, 지금 보이는 타깃이나 다른 감각으로 확인한 정보는 지우지 않습니다. 이 예제에서는 기억한 위치를 탐색을 마칠 때 지우며, 기억을 일정 시간 뒤에 잊게 하고 싶다면 타이머로 따로 규칙을 더합니다.


세 가지 우선순위로 트리 짜기

이제 BT_EnemyAI를 열고 다음 구조로 의사결정 모델을 만듭니다. 맨 위의 셀렉터가 왼쪽부터 추적과 공격, 기억 위치 탐색, 순찰과 대기의 세 가지를 우선순위대로 시도합니다.

Root
  |
  Selector (AI의 메인 의사결정, 우선순위: 전투/탐색 > 순찰)
    |
    +--- Sequence (플레이어 추적/공격)
    |      |
    |      +--- Decorator: Blackboard (IsPlayerDetected == True, Observer Aborts: Both)
    |      +--- Decorator: Blackboard (TargetActor Is Set, Observer Aborts: Self)
    |      |      (플레이어가 감지되었을 때만 이 브랜치를 실행)
    |      |
    |      +--- Task: Move To (Blackboard Key: TargetActor, Acceptable Radius: 150)
    |      |      (플레이어에게 접근)
    |      |
    |      +--- Task: Attack Player (새로운 커스텀 태스크 블루프린트)
    |      |      (공격 로직 - 애니메이션 재생, 데미지 적용 등)
    |      |
    |      +--- Service: Update Target Location (플레이어 위치를 지속적으로 TargetLocation에 업데이트)
    |             (부모인 Sequence 노드에 붙여, 해당 시퀀스가 실행되는 동안 주기적으로 실행되도록)
    |             (IsPlayerDetected이고 TargetActor가 유효할 때만 현재 위치 저장)
    |
    +--- Sequence (플레이어 탐색)
    |      |
    |      +--- Decorators: IsPlayerDetected == False AND TargetLocation Is Set
    |      |      (각 Blackboard 조건을 Sequence에 부착, Observer Aborts: Both)
    |      |      (플레이어를 놓쳤지만 마지막 위치 정보가 있을 때)
    |      |
    |      +--- Task: Move To (Blackboard Key: TargetLocation, Acceptable Radius: 50)
    |      |      (Force Success 데코레이터: 이동 실패도 아래 대기·위치 해제로 이어감)
    |      |      (마지막 감지 위치로 이동)
    |      |
    |      +--- Task: Wait (3.0초 대기)
    |      |      (해당 위치에서 잠시 탐색)
    |      |
    |      +--- Task: Clear Last Known Location (새로운 커스텀 태스크 블루프린트)
    |             (탐색을 마쳤으므로 블랙보드 컴포넌트의 Clear Value로 TargetLocation 키를 지움)
    |
    +--- 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초 대기)
                  (잠시 대기 후 다음 순찰 지점 탐색)

이 트리는 노드 배치를 글자로 그린 것이라 데코레이터와 서비스가 자식처럼 보이지만, 실제로는 해당 시퀀스나 태스크에 붙이는 요소입니다. 탐색 가지가 TargetLocation의 값이 0인지가 아니라 키의 Is Set을 검사한다는 점을 눈여겨봅니다. 원점 (0, 0, 0)도 조사할 만한 정상적인 위치일 수 있으므로, 값이 0인지로 판단하면 "설정되지 않음"과 "원점으로 설정됨"을 구분하지 못합니다.

조건이 바뀌면 진행 중인 행동도 바뀌어야 합니다. 그래서 블랙보드 데코레이터의 Notify Observer를 On Result Change로 두어 조건의 결과가 바뀔 때 알리게 하고, Observer Aborts를 Both로 설정합니다. Both는 조건이 바뀌었을 때 자기 가지와, 그 오른쪽에 있는 우선순위가 낮은 가지를 모두 중단할 수 있게 합니다. 예를 들어 순찰 중에 플레이어가 보이면 추적 가지의 조건이 참이 되어 순찰 가지가 중단되고, 추적 중에 시야를 잃으면 추적 가지 자신이 중단되어 셀렉터가 탐색 가지를 고릅니다.


우선순위와 기억 위치가 바뀌는 과정

세 가지와 그 사이의 전환을 그림으로 정리하면 다음과 같습니다.

현재 보이는 타깃과 기억한 위치를 다른 분기에서 처리합니다

소음은 기억 탐색, Sight 성공은 전투 우선, Sight 상실은 기억 유지 탐색, 조사 완료/위치 해제는 순찰이라는 실제 상태 전환이다.

PRIORITY · CURRENT SIGHT · MEMORY LOCATION

현재 보이는 타깃과 기억한 위치를 다른 분기에서 처리합니다

아래는 본문 Selector의 왼쪽부터 읽는 우선순위입니다. 청각 성공은 조사할 Stimulus Location을 만들며 현재 시각 확인 플래그를 true로 바꾸지 않습니다.

순찰탐색전투의전환조건순찰에서소음위치가생기면탐색한다. 순찰과탐색에서시각타깃이생기면전투를우선한다. 시각상실은기억위치탐색으로,탐색완료와위치키해제는순찰로연결한다. 그사이Task의진행중/성공/실패와Abort를본문설정으로처리한다.순찰 · 대기앞의 조건이 없음기억 위치 탐색시각 false · 위치 Is Set추적 · 공격시각 true · Actor Is Set소음 위치기억 있음조사 완료위치 해제Sight 성공Sight 성공Sight 상실 · 기억 유지
순찰탐색전투의전환조건순찰에서소음위치가생기면탐색한다. 순찰과탐색에서시각타깃이생기면전투를우선한다. 시각상실은기억위치탐색으로,탐색완료와위치키해제는순찰로연결한다. 그사이Task의진행중/성공/실패와Abort를본문설정으로처리한다.순찰 · 대기앞의 조건이 없음기억 위치 탐색시각 false위치 Is Set추적 · 공격시각 trueActor Is Set소음 위치기억 있음조사 완료위치 해제Sight성공Sight 상실기억 유지Sight 성공 · 우선
추적 탐색 순찰의 키 조건과 처리
우선순위조건실행완료·실패 조건
1 · 추적/공격IsPlayerDetected = true · TargetActor 키 설정Move To(TargetActor) → Attack Player공격 시점에도 대상·거리·권한을 검증
2 · 기억 위치 탐색IsPlayerDetected = false · TargetLocation 키 설정Move To(TargetLocation) → Wait 3초 → 위치 키 해제이 예제는 이동 실패도 Force Success로 대기·해제에 연결
3 · 순찰/대기앞의 두 분기로 행동할 수 없음도달 가능한 순찰 위치 찾기 → Move To → Wait 5초위치 찾기 실패 때 키 해제·실패 완료, 재시도 대기 설계

1 · 추적/공격

조건: IsPlayerDetected = true · TargetActor 키 설정

실행: Move To(TargetActor) → Attack Player

완료·실패 조건: 공격 시점에도 대상·거리·권한을 검증

2 · 기억 위치 탐색

조건: IsPlayerDetected = false · TargetLocation 키 설정

실행: Move To(TargetLocation) → Wait 3초 → 위치 키 해제

완료·실패 조건: 이 예제는 이동 실패도 Force Success로 대기·해제에 연결

3 · 순찰/대기

조건: 앞의 두 분기로 행동할 수 없음

실행: 도달 가능한 순찰 위치 찾기 → Move To → Wait 5초

완료·실패 조건: 위치 찾기 실패 때 키 해제·실패 완료, 재시도 대기 설계

키의 존재와 시야 확보를 함께 봅니다

TargetActor Is Set만으로 현재 시야를 보장하지 않습니다. 원점 (0,0,0)도 유효한 조사 위치일 수 있으므로 Vector 값이 0인지가 아니라 TargetLocation 키의 Is Set을 검사합니다.

조건 변화 때 분기 중단을 연결합니다

본문의 Blackboard Decorator는 Notify Observer를 On Result Change로 두고 필요한 Observer Aborts를 설정합니다. 중단한 공격의 늦은 완료 콜백이 새 공격을 끝내지 않도록 활성 상태와 이번 공격 실행에 속한 통지인지 함께 확인합니다. Abort에서는 이전 콜백·타이머를 정리합니다. 새 공격이 활성인 동안 옛 완료 통지가 도착하는 경우에는 활성 여부만으로 구분할 수 없습니다.

이 예의 조건

  • 본문과 원 도표에 제시된 사례의 입력·조건을 사용합니다. 설명용 수치나 독립 비교 경로는 각 단계에 표시합니다.
  • 현재 상태·값과 전환 근거의 위치는 모든 단계에서 같습니다. 조건이 맞지 않거나 실행되지 않은 경로를 성공한 동작으로 해석하지 않습니다.
관계도의 보충 설명
원 도표의 제목·노드·관계·조건·주석
범위원문
도표 제목순찰·탐색·전투의 전환 조건
관계·조건 설명순찰에서 소음 위치가 생기면 탐색한다. 순찰과 탐색에서 시각 타깃이 생기면 전투를 우선한다. 시각 상실은 기억 위치 탐색으로, 탐색 완료와 위치 키 해제는 순찰로 연결한다. 그 사이 Task의 진행 중/성공/실패와 Abort를 본문 설정으로 처리한다.
본문·주석추적·탐색·순찰의 키 조건과 처리
예의 값과 변화
관찰·상황값·보충 정보변화·이유
기억 탐색

소음 위치를 기억해 조사한다.

  • 상태: 기억 탐색
  • 목표: 기억 위치
  • 현재 시야에 없는 Actor를 전투 대상으로 확정하지 않는다.
시야 전투

Sight가 성공하면 전투 우선 상태가 된다.

  • 상태: 전투
  • 증거: 시야 성공
  • 기억 탐색보다 현재 보이는 목표의 정책이 우선한다.
상실·순찰

Sight 상실 뒤 기억을 조사하고 완료하면 순찰한다.

  • 중간: 기억 유지 탐색
  • 완료: 위치 해제→순찰
  • 시야 상실과 기억의 즉시 삭제를 같은 사건으로 만들지 않는다.

현재 보이는 타깃과 기억한 위치를 다른 분기에서 처리합니다

소음은 기억 탐색, Sight 성공은 전투 우선, Sight 상실은 기억 유지 탐색, 조사 완료/위치 해제는 순찰이라는 실제 상태 전환이다.

PRIORITY · CURRENT SIGHT · MEMORY LOCATION

현재 보이는 타깃과 기억한 위치를 다른 분기에서 처리합니다

아래는 본문 Selector의 왼쪽부터 읽는 우선순위입니다. 청각 성공은 조사할 Stimulus Location을 만들며 현재 시각 확인 플래그를 true로 바꾸지 않습니다.

순찰탐색전투의전환조건순찰에서소음위치가생기면탐색한다. 순찰과탐색에서시각타깃이생기면전투를우선한다. 시각상실은기억위치탐색으로,탐색완료와위치키해제는순찰로연결한다. 그사이Task의진행중/성공/실패와Abort를본문설정으로처리한다.순찰 · 대기앞의 조건이 없음기억 위치 탐색시각 false · 위치 Is Set추적 · 공격시각 true · Actor Is Set소음 위치기억 있음조사 완료위치 해제Sight 성공Sight 성공Sight 상실 · 기억 유지
순찰탐색전투의전환조건순찰에서소음위치가생기면탐색한다. 순찰과탐색에서시각타깃이생기면전투를우선한다. 시각상실은기억위치탐색으로,탐색완료와위치키해제는순찰로연결한다. 그사이Task의진행중/성공/실패와Abort를본문설정으로처리한다.순찰 · 대기앞의 조건이 없음기억 위치 탐색시각 false위치 Is Set추적 · 공격시각 trueActor Is Set소음 위치기억 있음조사 완료위치 해제Sight성공Sight 상실기억 유지Sight 성공 · 우선
추적 탐색 순찰의 키 조건과 처리
우선순위조건실행완료·실패 조건
1 · 추적/공격IsPlayerDetected = true · TargetActor 키 설정Move To(TargetActor) → Attack Player공격 시점에도 대상·거리·권한을 검증
2 · 기억 위치 탐색IsPlayerDetected = false · TargetLocation 키 설정Move To(TargetLocation) → Wait 3초 → 위치 키 해제이 예제는 이동 실패도 Force Success로 대기·해제에 연결
3 · 순찰/대기앞의 두 분기로 행동할 수 없음도달 가능한 순찰 위치 찾기 → Move To → Wait 5초위치 찾기 실패 때 키 해제·실패 완료, 재시도 대기 설계

1 · 추적/공격

조건: IsPlayerDetected = true · TargetActor 키 설정

실행: Move To(TargetActor) → Attack Player

완료·실패 조건: 공격 시점에도 대상·거리·권한을 검증

2 · 기억 위치 탐색

조건: IsPlayerDetected = false · TargetLocation 키 설정

실행: Move To(TargetLocation) → Wait 3초 → 위치 키 해제

완료·실패 조건: 이 예제는 이동 실패도 Force Success로 대기·해제에 연결

3 · 순찰/대기

조건: 앞의 두 분기로 행동할 수 없음

실행: 도달 가능한 순찰 위치 찾기 → Move To → Wait 5초

완료·실패 조건: 위치 찾기 실패 때 키 해제·실패 완료, 재시도 대기 설계

키의 존재와 시야 확보를 함께 봅니다

TargetActor Is Set만으로 현재 시야를 보장하지 않습니다. 원점 (0,0,0)도 유효한 조사 위치일 수 있으므로 Vector 값이 0인지가 아니라 TargetLocation 키의 Is Set을 검사합니다.

조건 변화 때 분기 중단을 연결합니다

본문의 Blackboard Decorator는 Notify Observer를 On Result Change로 두고 필요한 Observer Aborts를 설정합니다. 중단한 공격의 늦은 완료 콜백이 새 공격을 끝내지 않도록 활성 상태와 이번 공격 실행에 속한 통지인지 함께 확인합니다. Abort에서는 이전 콜백·타이머를 정리합니다. 새 공격이 활성인 동안 옛 완료 통지가 도착하는 경우에는 활성 여부만으로 구분할 수 없습니다.

이 예의 조건

  • 본문과 원 도표에 제시된 사례의 입력·조건을 사용합니다. 설명용 수치나 독립 비교 경로는 각 단계에 표시합니다.
  • 현재 상태·값과 전환 근거의 위치는 모든 단계에서 같습니다. 조건이 맞지 않거나 실행되지 않은 경로를 성공한 동작으로 해석하지 않습니다.

관계도의 보충 설명

원 도표의 제목·노드·관계·조건·주석
범위원문
도표 제목순찰·탐색·전투의 전환 조건
관계·조건 설명순찰에서 소음 위치가 생기면 탐색한다. 순찰과 탐색에서 시각 타깃이 생기면 전투를 우선한다. 시각 상실은 기억 위치 탐색으로, 탐색 완료와 위치 키 해제는 순찰로 연결한다. 그 사이 Task의 진행 중/성공/실패와 Abort를 본문 설정으로 처리한다.
본문·주석추적·탐색·순찰의 키 조건과 처리
예의 값과 변화
관찰·상황값·보충 정보변화·이유
기억 탐색

소음 위치를 기억해 조사한다.

  • 상태: 기억 탐색
  • 목표: 기억 위치
  • 현재 시야에 없는 Actor를 전투 대상으로 확정하지 않는다.
시야 전투

Sight가 성공하면 전투 우선 상태가 된다.

  • 상태: 전투
  • 증거: 시야 성공
  • 기억 탐색보다 현재 보이는 목표의 정책이 우선한다.
상실·순찰

Sight 상실 뒤 기억을 조사하고 완료하면 순찰한다.

  • 중간: 기억 유지 탐색
  • 완료: 위치 해제→순찰
  • 시야 상실과 기억의 즉시 삭제를 같은 사건으로 만들지 않는다.

위 그림은 셀렉터의 세 가지를 왼쪽부터 읽는 우선순위로 정리하고, 그 사이의 전환 조건을 보여 줍니다. 1순위인 추적과 공격은 IsPlayerDetected가 true이고 TargetActor 키가 설정되었을 때 Move To(TargetActor) 뒤에 Attack Player를 실행하며, 공격하는 순간에도 대상과 거리, 권한을 다시 검증합니다. 2순위인 기억 위치 탐색은 IsPlayerDetected가 false이고 TargetLocation 키가 설정되었을 때 Move To(TargetLocation), 3초 대기, 위치 키 해제를 차례로 실행하며, 이 예제는 이동이 실패해도 Force Success로 대기와 해제로 이어 갑니다. 3순위인 순찰과 대기는 앞의 두 가지로 행동할 수 없을 때 도달 가능한 순찰 위치를 찾아 이동하고 5초 기다립니다.

전환 화살표를 따라가면 순환이 보입니다. 순찰 중에 소음 위치가 생기면 탐색으로 넘어갑니다. 순찰이나 탐색 중에 시각 타깃이 생기면 전투가 우선합니다. 시각을 잃으면 기억을 유지한 채 기억 위치 탐색으로, 조사를 마쳐 위치 키를 비우면 다시 순찰로 돌아갑니다. 그림의 설명처럼 청각 감지는 조사할 Stimulus Location만 만들 뿐 현재 시각 확인 플래그를 true로 바꾸지 않으며, TargetActor의 Is Set만으로는 지금 보이는지를 보장하지 않으므로 두 조건을 함께 봅니다.

단계 그림은 이 순환을 세 장면으로 나눕니다. 첫 장면에서는 소음 위치를 기억해 조사하고, 둘째 장면에서는 시각 감지가 성공해 전투가 우선하는 상태가 되며, 셋째 장면에서는 시각을 잃은 뒤 기억한 위치를 조사하고 조사를 마치면 순찰로 돌아갑니다. 그림의 마지막 설명은 중단된 공격의 늦은 완료 통지를 다루는데, 이 부분은 아래의 공격 태스크에서 자세히 봅니다.


커스텀 태스크와 서비스 만들기

트리에 필요한 커스텀 태스크 세 개와 서비스 하나를 블루프린트로 만듭니다. 태스크는 콘텐츠 브라우저에서 우클릭해 Blueprint Class를 고르고, All Classes에서 BTTask_BlueprintBase를 검색해 부모로 선택해 만듭니다.

BTTask_AttackPlayer

공격 태스크는 그래프에서 Receive Execute AI 이벤트를 오버라이드합니다. 먼저 대상이 유효한지, 거리가 사거리 안인지, 공격할 수 있는 상태인지를 검사하고, 하나라도 통과하지 못하면 Finish Execute의 Success를 false로 호출해 끝냅니다. 통과하면 공격 몽타주를 재생하고, 실제로 피해를 주는 시점에 유효한 대상인지를 다시 확인합니다. 몽타주가 끝났다는 완료 콜백에서 Finish Execute(true)를 호출하고, 재생에 실패하면 false로 끝냅니다.

트리가 이 태스크를 중단할 때는 Receive Abort AI 이벤트가 실행됩니다. 여기서 공격 판정과 콜백 연결을 정리한 뒤 Finish Abort를 호출해 중단을 마칩니다. 주의할 점은 중단된 공격의 완료 콜백이 늦게 도착하는 경우입니다. 태스크가 활성인지만 검사하면, 새 공격이 시작되어 태스크가 다시 활성이 된 상태에서 옛 공격의 완료 통지가 그 검사를 통과해 새 공격을 끝내 버릴 수 있습니다.

그래서 활성 여부와 함께 그 통지가 이번 공격 실행에 속한 것인지도 검사합니다. 예를 들어 공격을 시작할 때마다 실행 번호를 하나씩 바꾸고, 완료 통지가 가지고 온 번호가 현재 번호와 같을 때만 Finish Execute로 연결합니다. Receive Abort AI에서는 이전 바인딩과 타이머처럼 이번 공격에서 쓴 자원을 함께 정리합니다.

BTTask_ClearLastKnownLocation

마지막 위치를 지우는 태스크도 BTTask_BlueprintBase를 부모로 만들고 Receive Execute AI를 오버라이드합니다. Owner Controller에서 Get Blackboard로 블랙보드 컴포넌트를 얻어 Clear Value를 호출하고, Key Name에 TargetLocation을 넣습니다. 그다음 Finish Execute를 Success true로 호출합니다.

BTTask_FindPatrolLocation

순찰 위치를 찾는 태스크 역시 BTTask_BlueprintBase를 부모로 만들고 Receive Execute AI를 오버라이드합니다. 이벤트의 Controlled Pawn이 유효한지 확인하고 현재 위치를 얻은 뒤, Get Random Reachable Point in Radius를 호출합니다. Origin에는 AI의 현재 위치를, Radius에는 순찰 반경(예: 1000.0)을 넣습니다.

이 노드가 돌려주는 Boolean 값이 true일 때만 찾은 위치를 블랙보드 컴포넌트의 Set Value as Vector로 PatrolLocation에 저장하고 Finish Execute(true)를 호출합니다. 실패하면 키를 비우고 Finish Execute(false)로 끝냅니다. 실패가 이어지면 셀렉터가 순찰 가지를 곧바로 다시 시도하므로, 재시도 사이에 잠시 기다리거나 유효한 시작 위치로 되돌리는 처리를 두어 같은 실패를 매 프레임 반복하지 않게 합니다.

BTS_UpdateTargetLocation

추적하는 동안 플레이어의 위치를 계속 갱신하는 서비스입니다. 콘텐츠 브라우저에서 Blueprint Class를 고르고 All Classes에서 BTService_BlueprintBase를 부모로 선택한 뒤, 이름을 BTS_UpdateTargetLocation으로 정합니다.

그래프에서 Receive Tick AI 이벤트를 오버라이드합니다. 비헤이비어 트리에 붙인 이 서비스의 디테일 패널에서 Interval을 0.5초 정도로 두고 Random Deviation도 확인합니다. 이 값은 실행 간격의 설정일 뿐, 정확히 0.5초마다 실행된다는 보장은 아닙니다.

이벤트의 Controlled Pawn을 Cast To Character(또는 Cast To BP_EnemyCharacter)로 확인하고, Owner Controller에서 Get Blackboard로 블랙보드 컴포넌트를 얻습니다. Get Value as Object에 TargetActor를 넣어 값을 읽고, 그 결과를 Cast To BP_PlayerCharacter로 캐스팅합니다. 캐스팅에 성공하고 IsPlayerDetected가 true일 때만 Get Actor Location으로 위치를 구해 Set Value as Vector로 TargetLocation에 저장합니다. 이 조건 덕분에 시야를 잃은 대상의 위치를 서비스가 계속 갱신하지 않습니다. 컴파일하고 저장합니다.


레벨에서 확인하기

레벨에 NavMeshBoundsVolume을 AI가 이동할 영역을 감싸도록 배치하고, P 키로 내비메시를 확인합니다. 그다음 BP_EnemyCharacter를 배치하고 게임을 플레이하며 AI의 행동을 살펴봅니다. AI가 순찰하다가 플레이어를 발견하면 쫓아가 공격하고, 시야를 잃으면 마지막으로 확인한 위치를, 소리만 들리면 소리가 난 위치를 조사해야 합니다. 탐색에서도 찾지 못하면 다시 순찰을 시작해야 합니다.

기대와 다르게 움직이면 플레이 중에 작은따옴표(') 키로 게임플레이 디버거를 열어 AI의 경로와 감각 정보를 보고, 비헤이비어 트리 에디터의 Blackboard 패널에서 실제 키 값을 확인합니다. 비헤이비어 트리 에디터의 디버그 드롭다운에서 실행 중인 AI를 고르면 지금 활성인 노드도 실시간으로 볼 수 있습니다.


더 다듬을 수 있는 부분

이 모델은 기본적인 의사결정의 예이며, 실제 게임에서는 여기에 더 많은 로직이 붙습니다. 근접 공격, 원거리 공격, 스킬 사용 같은 다양한 공격 패턴은 Attack Player 태스크 안에서 나누거나 별도의 태스크로 분리합니다. EQS의 기본 활용법에서 만든 엄폐 쿼리를 더하면 회피와 엄폐 행동을 넣을 수 있고, 피해를 입었을 때 반응 애니메이션을 재생하거나 후퇴하는 가지도 더할 수 있습니다. 여러 AI가 협동하거나 경쟁하는 그룹 AI, 웅크리거나 빠르게 달리는 등 플레이어의 행동에 따라 감지 거리나 확률이 달라지는 감지 수준도 흔히 더하는 확장입니다.


정리

  • AI의 행동 순환은 감지 이벤트가 블랙보드 키를 바꾸고, 비헤이비어 트리가 그 키를 조건으로 가지를 고르는 구조로 만듭니다.
  • 시각은 TargetActor, 위치, IsPlayerDetected를 함께 바꾸고, 청각은 시각 타깃이 없을 때 조사할 위치만 기록합니다.
  • 셀렉터의 세 가지는 추적과 공격, 기억 위치 탐색, 순찰과 대기의 우선순위를 가지며, 위치 키는 값이 0인지가 아니라 Is Set으로 검사합니다.
  • 블랙보드 데코레이터의 Notify Observer를 On Result Change로, Observer Aborts를 Both나 Self로 두어 조건이 바뀔 때 진행 중인 가지를 중단합니다.
  • 커스텀 태스크는 모든 경로에서 Finish Execute나 Finish Abort로 끝내고, 중단된 실행의 늦은 콜백이 새 실행을 끝내지 않도록 실행 번호 같은 구분을 둡니다.

연습 문제

1. 원점 위치와 새 감지의 우선순위

시각을 잃어 IsPlayerDetected가 false이고 TargetActor는 비어 있습니다. 마지막으로 확인한 위치 (0, 0, 0)이 TargetLocation 키에 설정되어 있습니다. 셀렉터는 어느 가지를 고를까요? 이동이 실패했고 Force Success가 붙어 있다면 다음 단계는 무엇일까요? 3초 대기 도중 새로 시각 감지에 성공해 IsPlayerDetected가 true가 되고 유효한 TargetActor가 설정되었다면, 원래 탐색이 끝날 때까지 기다려야 할까요?

해설 보기

TargetLocation이 Is Set 상태이므로 기억 위치 탐색 가지를 고릅니다. 원점 벡터를 설정되지 않은 값으로 취급해 순찰로 건너뛰지 않습니다.

이 글의 Force Success 설정에서는 이동이 실패해도 3초 대기와 위치 해제로 이어집니다. 다만 이것은 AI가 그 위치에 실제로 도착했다는 뜻은 아닙니다. 대기 중에 새 시각 타깃이 생기면, 블랙보드 조건의 On Result Change와 Observer Aborts: Both 설정이 탐색 가지를 중단하고 우선순위가 높은 추적과 공격 가지를 고르게 합니다. 그래서 원래 탐색을 끝까지 기다리지 않습니다. 이때 중단된 대기나 공격의 이전 완료 콜백을 새 실행의 완료로 받아들이지 않도록 정리해 둡니다.

2. 추적 중에 들린 소리

AI가 보이는 플레이어를 쫓는 동안, 다른 방향에서 플레이어가 던진 물건이 떨어지는 소음이 감지되었습니다. 이 소음의 Stimulus Location을 TargetLocation에 바로 써도 될까요?

해설 보기

쓰지 않습니다. 이 글의 규칙에서 청각 감지는 지금 시각 타깃이 없을 때만 TargetLocation을 바꿉니다. 추적 중에는 서비스가 보이는 플레이어의 위치로 TargetLocation을 갱신하고 있으므로, 소음 위치를 덮어쓰면 추적 대상과 조사할 위치가 어긋납니다.

나중에 시야를 잃으면 TargetLocation에는 마지막으로 본 위치가 남아 있어 그곳을 탐색합니다. 소음을 무시하지 않고 따로 기억하고 싶다면, 별도의 키를 두고 시각 정보와 섞이지 않게 관리하는 식으로 규칙을 넓힙니다.

3. 새 공격을 끝내 버린 옛 통지

플레이어가 사거리 밖으로 잠깐 벗어나 공격 태스크가 중단되었고, 곧 다시 사거리 안으로 들어와 새 공격이 시작되었습니다. 그런데 새 공격의 몽타주가 절반쯤 재생된 순간 태스크가 성공으로 끝나 버립니다. 무엇이 원인일 수 있고, 어떻게 막을 수 있을까요?

해설 보기

중단된 첫 공격의 몽타주 완료 콜백이 늦게 도착했을 가능성이 큽니다. 태스크가 활성인지만 검사하고 있다면, 새 공격으로 다시 활성이 된 태스크에서 옛 통지가 검사를 통과해 Finish Execute(true)를 호출하게 됩니다.

공격을 시작할 때마다 실행 번호를 바꾸고, 완료 통지가 가지고 온 번호가 지금 번호와 같을 때만 Finish Execute로 연결하면 옛 통지를 걸러 낼 수 있습니다. 또 Receive Abort AI에서 이전 공격의 바인딩과 타이머를 정리해, 중단된 실행에서 남은 통지가 애초에 오지 않게 합니다.

블랙보드 데코레이터의 Observer Aborts와 이벤트 기반 판단은 언리얼 엔진 공식 문서의 비헤이비어 트리 개요에서 확인할 수 있습니다.

이것으로 8장을 마칩니다. 8장에서는 비헤이비어 트리와 블랙보드로 AI 판단의 뼈대를 세우고, EQS로 행동할 위치를 고르고, 내비게이션으로 목표까지 이동하고, AI Perception으로 보고 들은 것만 블랙보드에 넘긴 뒤, 이 모두를 엮어 순찰, 감지, 추적, 공격, 탐색이 순환하는 AI를 만들었습니다. 다음 장의 게임 모드, 스테이트 블루프린트부터는 게임 모드와 게임 스테이트, 플레이어 컨트롤러와 폰, 리플리케이션, 체크포인트와 세이브, 게임플레이 능력 시스템까지 게임 전체를 받치는 게임플레이 프레임워크를 다룹니다.