간단한 AI 의사결정 모델 구현
센서·블랙보드·비헤이비어 트리·내비게이션을 연결해 순찰·감지·추적·공격·탐색 순환을 구현합니다.
지금까지 우리는 비헤이비어 트리, EQS, 내비게이션, 그리고 센서 시스템이라는 AI 구축의 핵심 도구들을 개별적으로 살펴보았습니다.
이제 이 모든 요소들을 결합하여, 플레이어를 감지하고, 추적하고, 공격하거나, 플레이어를 놓치면 순찰하는 간단한 AI 의사결정 모델을 구현해보겠습니다.
이는 AI가 인지 → 판단 → 행동의 순환을 통해 작동하는 기본적인 패턴을 보여줄 것입니다.
AI 의사결정 모델의 목표
우리가 구현할 AI는 다음과 같은 의사결정 과정을 따릅니다.
초기 상태: 순찰(Patrol) 또는 대기(Idle)
플레이어 감지: AI Perception을 통해 플레이어를 시각으로 확인하거나 청각으로 마지막 소음 위치를 얻습니다.
추적/전투: 현재 보이는 플레이어를 추적하고, 공격 시점에도 대상·거리·권한 조건을 확인합니다. 소리만 들었을 때는 발생 위치를 조사합니다.
플레이어 놓침: 시야를 잃으면 마지막으로 확인한 위치를 탐색합니다. 청각 성공 이벤트도 조사할 위치를 제공하며 현재 시야 확보로 취급하지 않습니다.
탐색 실패: 마지막 감지 위치에서도 플레이어를 찾지 못하면 다시 순찰 상태로 돌아갑니다.
AI 의사결정 시스템 구현을 위한 준비물
- 플레이어 캐릭터:
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가 이동할 수 있는 영역 설정
AI 의사결정 구현 단계별 가이드
이전 절에서 다룬 내용을 바탕으로 각 요소를 이미 설정했다고 가정하고, 이제 이들을 비헤이비어 트리에 결합하는 데 중점을 둡니다.
블랙보드 키 추가
BB_EnemyAI 블랙보드에 다음 키들을 추가합니다.
TargetActor(Object, Base Class:Actor)TargetLocation(Vector)IsPlayerDetected(Boolean) - 이 실습에서는 현재 시각으로 확인했는지 여부PatrolLocation(Vector) - AI가 순찰할 목표 위치
AI 컨트롤러 (AIC_Enemy) 설정
AIC_Enemy의 AI Perception 컴포넌트에서 On Target Perception Updated 이벤트를 처리하여 블랙보드를 업데이트합니다.
이 예제는 플레이어 1명을 대상으로 하며 IsPlayerDetected를 현재 시각 확인 여부로 정의합니다. 이벤트의 Actor를 플레이어로 확인하고 Stimulus의 감각 종류를 분리합니다. 초기화된 Blackboard Component의 Set Value as Object/Vector/Bool과 Clear Value를 사용합니다.
- Sight 성공:
TargetActor와 확인한TargetLocation을 저장하고IsPlayerDetected = true로 설정합니다. - Sight 상실: 현재 타깃에 해당할 때
IsPlayerDetected = false,TargetActor는 비우고 기존TargetLocation은 유지합니다. - Hearing 성공: 현재 시각 타깃이 없을 때만
Stimulus Location을TargetLocation에 저장합니다.IsPlayerDetected를 true로 바꾸거나 보이지 않는 Actor의 현재 위치를 읽지 않습니다. - Hearing 실패/만료: 현재 시야나 다른 감각의 유효한 증거를 지우지 않습니다. 여기서는 기억 위치를 탐색 완료 때 지우며, 별도의 기억 제한 시간을 두려면 타이머 정책을 추가합니다.
비헤이비어 트리 (BT_EnemyAI) 구현
이제 BT_EnemyAI를 열고 다음 구조로 AI의 의사결정 모델을 만듭니다. 코드 모양의 표기는 노드 배치 설명이며, Decorator와 Service는 해당 Sequence/Task에 부착합니다. Vector의 Is Set을 사용해 유효한 원점 (0,0,0)과 미설정 상태를 구분합니다. Blackboard 데코레이터의 Notify Observer는 On Result Change로 두고, Both가 자기 분기와 오른쪽의 낮은 우선순위 분기를 중단하도록 설정합니다.
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 (새로운 커스텀 태스크 블루프린트)
| (탐색을 마쳤으므로 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초 대기)
(잠시 대기 후 다음 순찰 지점 탐색)위 비헤이비어 트리 구조에 필요한 커스텀 태스크를 생성합니다.
BTTask_AttackPlayer (공격 태스크)- 콘텐츠 브라우저에서 마우스 우클릭 >
블루프린트 클래스(Blueprint Class)>All Classes에서BTTask_BlueprintBase를 검색하여 선택합니다. - 그래프 탭:
Receive Execute AI이벤트를 오버라이드합니다. - 대상 유효성·거리·공격 가능 조건을 검사하고 실패하면
Finish Execute(false)로 끝냅니다. 통과하면 몽타주를 재생하고 공격 시점에 유효한 피해 대상을 다시 확인합니다. - 완료 콜백에서
Finish Execute(true), 재생 실패에서는 false로 끝냅니다.Receive Abort AI에서는 공격 판정·콜백을 정리하고Finish Abort로 중단을 마칩니다. 중단된 태스크의 늦은 콜백이 새 공격을 완료시키지 않도록 활성 상태도 검사합니다.
BTTask_ClearLastKnownLocation (마지막 위치 지우기 태스크)BTTask_BlueprintBase를 상속받아 생성합니다.- 그래프 탭:
Receive Execute AI이벤트를 오버라이드합니다. Get Blackboard Component노드를 호출하여 블랙보드 참조를 얻습니다.- 블랙보드 참조에서
Clear Value노드를 호출하고Key Name핀에TargetLocation(키 이름)을 연결합니다. Finish Execute노드를 호출하고Success를True로 설정합니다.
BTTask_FindPatrolLocation (순찰 위치 찾기 태스크)BTTask_BlueprintBase를 상속받아 생성합니다.- 그래프 탭:
Receive Execute AI이벤트를 오버라이드합니다. Receive Execute AI의Controlled Pawn을 유효성 검사하고 현재 위치를 얻습니다.Get Random Reachable Point in Radius노드를 호출합니다.Origin은 AI의 현재 위치.Radius는 순찰 반경 (예: 1000.0).
- 반환 Boolean이 true일 때만 찾은 위치를 Blackboard Component의
Set Value as Vector로PatrolLocation에 저장하고Finish Execute(true)를 호출합니다. - 실패하면 키를 비우고
Finish Execute(false)로 끝냅니다. 연속 실패 시 재시도 간 대기나 유효한 시작 위치 복구를 두어 매 프레임 같은 실패를 반복하지 않게 합니다.
BTService_UpdateTargetLocation
플레이어를 추적하는 동안 플레이어의 위치를 지속적으로 업데이트하는 서비스입니다.
- 콘텐츠 브라우저에서 마우스 우클릭 >
블루프린트 클래스(Blueprint Class)>All Classes에서BTService_BlueprintBase를 검색하여 선택합니다. - 이름을
BTS_UpdateTargetLocation으로 지정합니다.
Receive Tick AI이벤트를 오버라이드합니다.- Behavior Tree에 붙인 Service의 Details에서
Interval을0.5초 정도로 설정하고Random Deviation도 확인합니다. 정확한 0.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 Object의Return Value에서Cast To BP_PlayerCharacter를 연결합니다.- 캐스팅 성공 및
IsPlayerDetected = true일 때만Get Actor Location을 호출합니다. 시야를 잃은 대상의 위치를 이 서비스가 계속 갱신하지 않게 합니다. - 이 위치를
Blackboard Component의Set Value as Vector노드를 통해TargetLocation블랙보드 키에 저장합니다. - 컴파일 및 저장합니다.
레벨 배치 및 테스트
레벨에 Nav Mesh Bounds Volume이 AI 이동 영역을 포함하도록 배치하고 P 키를 눌러 내비메시를 확인합니다.
BP_EnemyCharacter를 레벨에 배치합니다.
게임을 플레이하고 AI의 행동을 관찰합니다.
- AI가 순찰하다가 플레이어를 발견하면 추적하고 공격합니다.
- 플레이어가 시야에서 사라지거나 소리만 들리면, AI는 마지막으로 플레이어를 본 위치로 이동하여 잠시 탐색합니다.
- 탐색에도 실패하면 다시 순찰을 시작합니다.
- PIE의 Gameplay Debugger(기본 apostrophe 키)에서 AI 경로·감각 정보를 확인하고, 트리 에디터의 Blackboard 패널에서 실제 키 값을 봅니다.
- 비헤이비어 트리 에디터에서
디버그(Debug)드롭다운 메뉴를 통해 실행 중인 AI를 선택하고, 트리의 활성화된 노드를 실시간으로 확인합니다.
추가적인 개선 사항
이 모델은 기본적인 의사결정의 예시이며, 실제 게임에서는 더욱 복잡한 로직이 추가됩니다.
- 다양한 공격 패턴: 근접 공격, 원거리 공격, 스킬 사용 등을
Attack Player태스크 내부에서 또는 별도의 태스크로 분리하여 구현. - 회피 및 엄폐: EQS를 활용하여 엄폐 위치를 찾고 이동하는 로직 추가.
- 피해 반응: 데미지를 입었을 때 특정 애니메이션을 재생하거나, 후퇴하는 행동 추가.
- 그룹 AI: 여러 AI가 협동하거나 경쟁하는 로직 구현.
- 감지 수준: 플레이어의 행동(예: 웅크리기, 빠르게 달리기)에 따라 감지될 확률이나 거리가 달라지도록 설정.