이 예제는 언리얼 매뉴얼 입니다. 처음에 교재가 여려워 검색하다 비슷한 예제가 있어 캡쳐해 봤습니다.
따라 해봤는데 안움직이는데 아직 이유는 모르겠습니다. ㅠㅠ 이 가이드에서는 순찰하거나 플레이어를 추격하는 AI 캐릭터를 비헤이비어 트리로 구성하는 방법을 알아봅니다.
비헤이비어 트리 퀵 스타트 가이드에서는 플레이어를 보고 반응하여 추격하는 적 AI를 구성하는 방법을 학습합니다. 아래 예시 영상에서 볼 수 있듯이, 플레이어가 시야에서 사라지면 AI는 몇 초 후(원하는 대로 조정 가능) 추격을 포기하고 플레이어를 다시 발견할 때까지 주변을 랜덤하게 배회합니다.
가이드에 따라 학습을 마치면 다음과 같은 시스템을 이해할 수 있습니다.
블루프린트 비주얼 스크립팅(Blueprint Visual Scripting)
AI 컨트롤러(AI Controller)
블랙보드(Blackboard)
비헤이비어 트리
비헤이비어 트리 서비스(Behavior Tree Service)
비헤이비어 트리 데코레이터(Behavior Tree Decorator)
비헤이비어 트리 태스크(Behavior Tree Task)
1 - 필수 프로젝트 구성
우선 AI 캐릭터가 환경을 배회하기 위해 필요한 에셋을 사용하여 프로젝트를 구성합니다.
이 가이드에서는 새로운 블루프린트 삼인칭 템플릿(Blueprint Third Person Template) 프로젝트를 사용합니다.
NavMeshBoundsVolume을 선택한 채R을 누른 다음 볼륨이 레벨 전체를 덮도록 스케일을 조절합니다. 그러면 AI 캐릭터가 주변 환경을 돌아다닐 수 있는 내비게이션 메시(Navigation Mesh)가 생성됩니다.P를 눌러 내비메시를 뷰포트에 표시할지 여부를 토글할 수 있습니다. 녹색 영역은 이동 가능한 위치를 나타냅니다.
게임플레이 중에는Show Navigation콘솔 명령으로 내비메시의 표시 여부를 토글할 수 있습니다.
프로젝트 구성이 끝났으니 다음 단계에는블랙보드(Blackboard)에셋을 구성하겠습니다.
2 - 블랙보드 구성
이번 단계에는 AI의 두뇌 역할을 할블랙보드(Blackboard)에셋을 구성합니다. AI가 알아야 하는 모든 요소는블랙보드 키(Blackboard Key)를 통해 참조할 수 있습니다. 여기서는 AI가 플레이어에 대한 직접적인 시야를 확보했는지 여부에 상관없이 플레이어를 트래킹하는 키를 생성하고, AI가 플레이어를 쫓지 않을 때 이동할 수 있는 위치를 확보하겠습니다.
콘텐츠 드로어(Content Drawer)에서+추가(+Add)를 클릭하고인공 지능(Artificial Intelligence)에서블랙보드를 선택한 뒤BB_Enemy로 이름 짓습니다.
BB_Enemy블랙보드 안에서새 키(New Key)버튼을 클릭하여오브젝트(Object)를 선택합니다. 블랙보드에셋은 두 개의 패널로 구성됩니다.블랙보드패널에서는블랙보드 키(모니터링할 변수)를 추가하고 트래킹할 수 있으며,블랙보드 디테일(Blackboard Details)패널에서는 키의 이름을 정하고 키 타입을 지정할 수 있습니다.
키 타입(Key Type)이부울(Bool)인키를 하나 더 추가하고HasLineOfSight로 이름 짓습니다. 이 키는 AI가 플레이어에 대한 시야를 확보했는지 여부를 트래킹하는 데 사용됩니다.
키 타입이벡터(Vector)인키를 하나 더 추가하고PatrolLocation으로 이름 짓습니다. 이 키는 AI가 플레이어를 추격하는 중이 아닐 때 이동 가능한 레벨 내 위치를 트래킹하는 데 사용됩니다.
트래킹해야 하는 항목들이 반영된블랙보드가 구성되었습니다. 다음 단계에는비헤이비어 트리(Behavior Tree)의 레이아웃을 설정합니다.
3 - 비헤이비어 트리 레이아웃
이 단계에는비헤이비어 트리(Behavior Tree)의 흐름과 AI가 진입할 스테이트의 레이아웃을 구성합니다. AI에게 기대하는 스테이트를 갖춘비헤이비어 트리의 레이아웃을 시각적 흐름으로 구성하면 해당 스테이트에 진입하는 데 필요한 로직과 규칙의 타입에 관한 아이디어를 얻을 수 있습니다.
콘텐츠 드로어(Content Drawer)에서+추가(+Add)를 클릭한 후인공 지능(Artificial Intelligence)에서비헤이비어 트리를 선택하고BT_Enemy로 이름 짓습니다.
이름 규칙은 다양할 수 있지만, 일반적으로는 에셋 타입을 이름의 접두사로 붙이는 방식이 좋습니다.
방금 생성한블랙보드 키를 찾을 수 없다면 노란색 화살표를 클릭하여블랙보드 에셋을 초기화한 다음Enemy_BB를 재할당하여 키를 새로고침합니다.
비헤이비어 트리는 세 가지 패널로 구성됩니다.비헤이비어 트리그래프에서는 비헤이비어를 정의하는 분기와 노드의 레이아웃을 시각적으로 구성할 수 있고,디테일(Details)패널에서는 노드의 프로퍼티를 정의할 수 있으며,블랙보드에서는 게임이 실행 중일 때의블랙보드 키와 키의 현재 값을 확인하여 디버깅에 활용할 수 있습니다.
그래프에서루트(Root)를 좌클릭하고 드래그하여Selector노드를 추가합니다. 컴포짓(Composite)은 흐름 제어의 형태이며, 연결된 자손 분기의 실행 방식을 결정합니다. 컴포짓설명
셀렉터(Selector)
왼쪽에서 오른쪽 순서로 분기를 실행하며, 보통은 복수의 서브트리 중 하나를 선택하는 데 사용됩니다. 셀렉터는 성공적으로 실행할 수 있는 서브트리를 찾으면 이동을 멈춥니다. 예를 들어 AI가 플레이어를 성공적으로 추격하고 있다면, 분기의 실행이 완료될 때까지 해당 분기에 머물다가 셀렉터의 부모 컴포짓으로 이동하여 결정 흐름을 계속하게 됩니다.
시퀀스(Sequence)
왼쪽에서 오른쪽 순서로 분기를 실행하며, 보통은 복수의 자손을 순서대로 실행하는 데 사용됩니다. 시퀀스는 셀렉터와 달리 실패하는 노드에 도달할 때까지 자손을 계속해서 실행합니다. 예를 들어 플레이어를 향해 움직여서 플레이어가 일정 거리 안에 들어왔는지 확인한 다음 회전하여 공격하게 하는 시퀀스가 있다고 합시다. 플레이어가 일정 거리 안에 들어왔는지 확인하는 부분이 실패하면, 회전 후 공격 액션은 실행되지 않습니다.
단순 병렬(Simple Parallel)
단순 병렬에는 두 개의 '연결'이 있습니다. 첫 번째는 메인 태스크(Main Task)이며, 컴포짓이 아닌 태스크(Task) 노드에만 할당할 수 있습니다. 두 번째 연결인 백그라운드 분기(Background Branch)는 메인 태스크가 실행 중일 동안 실행됩니다. 단순 병렬은 프로퍼티에 따라 메인 태스크가 완료된 직후에 완료될 수도 있고, 아니면 백그라운드 분기도 완료될 때까지 대기할 수도 있습니다.
Selector노드의디테일패널에서노드 이름(Node Name)을AI Root로 변경합니다. 그래프에 있는 노드의 이름을 변경하면 노드의 역할을 한눈에 알아보기 좋습니다. 이번 예시에서 이 노드를AI Root로 변경하는 이유는 이 노드가 비헤이비어 트리의 실제 '루트'로서 자손 분기 사이를 전환하기 때문입니다. 비헤이비어 트리를 생성할 때 자동으로 추가되는 디폴트 루트 노드는 비헤이비어 트리의 프로퍼티를 환경설정할 때와 사용 중인 블랙보드 에셋을 할당할 때 사용됩니다.
AI Root를 좌클릭하고 드래그하여Sequence노드를 추가하고Chase Player로 이름 짓습니다. 여기서는 시퀀스 노드를 사용하여 AI에게 액션 시퀀스를 실행하도록 하겠습니다. 플레이어 방향으로 회전한 다음, 이동 속도를 변경하고, 플레이어를 추격하기 위해 이동하는 시퀀스입니다.
AI Root노드를 좌클릭하고 드래그하여Sequence노드를 추가하고Patrol로 이름 짓습니다. AI에게Sequence노드를 사용하여 맵에서 랜덤 위치를 찾고, 그 위치로 이동하고, 그 위치에서 잠시 대기하다가, 다시 새로운 위치를 찾아 움직이는 프로세스를 반복시키겠습니다.
이 숫자가 실행 순서를 나타냅니다. 비헤이비어 트리는 왼쪽에서 오른쪽, 위에서 아래 순서로 실행되기 때문에 노드의 배열도 중요합니다. 보통 AI에게 중요도가 높은 액션을 왼쪽에 배치하고, 덜 중요한 액션 또는 예비 비헤이비어를 오른쪽에 배치하는 것이 일반적입니다. 자손 분기 역시 동일한 방식으로 작동하며, 자손 분기 중 하나라도 실패하면 전체 분기가 실행을 중지하고 트리를 다시 거슬러 올라갑니다. 예를 들어Chase Player분기가 실패하면AI Root를 거슬러 올라가Patrol이전으로 돌아가게 됩니다.
노드의 우측 상단에는 숫자가 있습니다.
AI Root에서 드래그하여Wait태스크를Patrol오른쪽에 추가하고대기 시간(Wait Time)을1.0으로 설정합니다. 이 노드가 보라색인 것은태스크(Task)노드라는 의미입니다. 태스크 노드는비헤이비어 트리가 수행할 액션입니다.Wait태스크는비헤이비어 트리가 Chase Player와 Patrol에 모두 실패했을 때 취할 대기 액션입니다.
Chase Player에서 드래그하여Rotate to Face BBEntry노드를 추가합니다. 이태스크를 사용하면 원하는블랙보드 엔트리(Blackboard Entry)가 회전하도록 지정할 수 있습니다. 여기서는Enemy Actor(플레이어) 방향으로 회전합니다. 이렇게 노드를 추가하고디테일패널을 보면블랙보드 키가 자동으로EnemyActor로 설정되는데, 액터 블랙보드 변수라는 필터를 적용한 목록의 첫 번째 변수이기 때문입니다. 정밀도(Precision)옵션으로 성공 조건 범위를 조정할 수도 있고,노드 이름을 변경할 수도 있습니다.
툴바에서새 태스크(New Task)버튼을 클릭합니다. 여기서는 내장된 태스크를 사용할 수 있을 뿐만 아니라, 직접 커스터마이징하고 정의할 수 있는 추가적인 로직을 갖는 커스텀 태스크를 생성하여 할당할 수도 있습니다. 이 태스크는 플레이어를 추격할 수 있도록 AI의 이동 속도를 변경하는 데 사용됩니다. 새 태스크를 생성하면 새블루프린트가 자동으로 생성되고 실행됩니다.
콘텐츠 드로어에서 새 에셋의 이름을BTT_ChasePlayer로 변경합니다. 태스크(Task),데코레이터(Decorator),서비스(Service)를 새로 생성한 뒤에는 바로 이름을 변경하는 것이 좋습니다. 적절한 이름 규칙은 생성한 에셋의 이름에 에셋 타입별 접두사를 추가하는 것입니다. 예를 들어 비헤이비어 트리 태스크에는BTT, 비헤이비어 트리 데코레이터에는BTD, 비헤이비어 트리 서비스에는BTS접두사를 지정하면 좋습니다.
BT_Enemy안에서BTT_ChasePlayer와Move To태스크를 추가합니다. 새로 추가한 태스크에는 아직 아무 로직도 없지만, AI 캐릭터가 이동 속도를 변경하여 EnemyActor(플레이어)를 향해 이동하는 로직을 나중에 추가하겠습니다.
새태스크를 생성하여BTT_FindRandomPatrol로 이름 짓고Patrol에 연결합니다.
Move To뒤에Wait태스크를 추가하고대기 시간을4.0으로,랜덤 편차(Random Deviation)를1.0으로 설정합니다. 그러면 AI에게 PatrolLocation에서 3~5초간 대기하도록 지시하게 됩니다(랜덤 편차로 인해 대기 시간에 1초의 편차가 추가됩니다).
비헤이비어 트리프레임워크가 완성되었습니다. 다음 단계에는 AI의 이동 속도를 변경하고, AI가 순찰 중에 이동할 랜덤 위치를 찾고, AI가 플레이어를 추격할지 순찰할지 결정하는 로직을 추가하겠습니다.
4 - 태스크 구성 - 플레이어 추격
이번 단계에는 플레이어를 추격할 때 이동 속도를 변경하는플레이어 추격 태스크(Chase Player Task)를 구성하겠습니다.
BTT_ChasePlayer안에서 우클릭하고이벤트 Receive Execute AI노드를 추가합니다. 이벤트 Receive Execute AI 노드는비헤이비어 트리안에서 이 태스크가 활성화될 때 트리거됩니다.
에이전트가 AI 컨트롤러인 경우 항상 AI 버전의 이벤트 Receive Execute , 이벤트 Receive Abort , 이벤트 Receive Tick 을 선택해야 합니다. 일반 이벤트 버전 및 AI 이벤트 버전이 모두 구현되어 있다면 더 적합한 버전 하나만 호출됩니다. 즉, AI의 경우에는 AI 버전이 호출되고 이외의 경우에는 일반 버전이 호출됩니다.
Controlled Pawn핀에서Enemy_Character에 형변환(Cast to Enemy_Character)노드를 사용합니다. Enemy_Character라는 AI가캐릭터 블루프린트(Character Blueprint)에 액세스하도록 형변환(Cast) 노드를 사용하는 것입니다.
콘텐츠 드로어(Content Drawer)에서Enemy_Character블루프린트를 실행하여Update Walk Speed라는함수(Function)를 추가합니다. 이 함수는 비헤이비어 트리에서 호출되어 AI의 이동 속도를 변경하는 데 사용됩니다.
기술적으로는 Chase Player 태스크의 형변환 노드로부터 캐릭터 무브먼트(Character Movement) 컴포넌트에 액세스하여 해당 태스크 안에서 이동 속도를 조정할 수 있지만, 비헤이비어 트리가 서브 오브젝트의 프로퍼티를 직접 변경하게 하는 것이 권장되는 모범 사례라고 할 수는 없습니다. 그 대신 비헤이비어 트리가 캐릭터 안의 함수를 호출하여 필요에 따라 조정하도록 하겠습니다.
Update Walk Speed함수의디테일(Details)패널에서NewWalkSpeed라는플로트(Float)입력을 추가합니다.
컴포넌트(Components) 탭에서캐릭터 무브먼트컴포넌트를 드래그합니다.
캐릭터 무브먼트핀을 클릭하고 드래그하여 액션 메뉴에Set Max Walk Speed를 입력한 다음 메뉴에서Set Max Walk Speed를 클릭합니다.
Set Max Walk Speed를 아래와 같이 연결합니다.
이 함수를 비헤이비어 트리에서 호출할 때는 값을 새로운 속도로 사용하도록 전달할 수 있습니다.
BTT_ChasePlayer태스크로 돌아와As Enemy Character노드에서Update Walk Speed를 호출하고500.0으로 설정한 후 다음과 같이 연결합니다.
생성한 Update Walk Speed 함수가 보이지 않나요? Enemy_Character 블루프린트를 플레이어 추격 태스크 에 추가하려면 우선 컴파일(Compile) 해야 할 수도 있습니다.
Update Walk Speed뒤에Finish Execute노드를 두 개 추가하여 아래와 같이 연결합니다.여기서는 Enemy_Character로의 형변환이 성공하면 태스크가 성공한 것으로 판정합니다. Sucess를체크합니다 . 제어되는 폰이 Enemy_Character가 아닌 경우 태스크가 성공하지 못했다고 판정하여 태스크를 중단하도록 처리해야 합니다. Sucess를 언체크합니다.
New Walk Speed핀을 우클릭하고 변수로 승격한 후ChaseSpeed로 명명합니다.
ChaseSpeed의인스턴스 편집가능(Instance Editable)옵션을 활성화합니다. 인스턴스 편집가능변수로 승격하면최대 걷기 속도(Max Walk Speed)값을 블루프린트 외부에서 설정할 수 있으며,비헤이비어 트리내부에서 프로퍼티로 활용할 수 있습니다. 이제Enemy_Character블루프린트로 전송되는추격 속도(Chase Speed)값을 쉽게 변경하여 AI가 플레이어를 추격하는 속도를 미세조정할 수 있습니다.
플레이어 추격 태스크(Chase Player Task)를 완성했으니, 다음 단계에는 AI가 이동할 랜덤 위치를 구하는랜덤 순찰 탐색 태스크(Find Random Patrol Task)로직을 구성해 보겠습니다.
5 - 태스크 구성 - 랜덤 순찰 탐색
이 단계에는 AI가 플레이어를 추격하지 않을 때 랜덤 위치로 이동하도록랜덤 순찰 탐색 태스크를 구성해 보겠습니다.
블루프린트 비헤이비어 트리 태스크를 구현하면 반복작업을 빠르게 처리하기 좋지만, 퍼포먼스가 중요하다면 네이티브 비헤이비어 트리 태스크로 구현할 것을 추천드립니다.
다음 세팅을 사용하여As Enemy Character에서Update Walk Speed를 호출하고New Walk Speed를 변수로 승격한 후Patrol Speed로 이름 짓습니다
변수 이름(Variable Name):PatrolSpeed
인스턴스 편집가능:활성화
Patrol Speed(기본값):125.0
순찰 중일 동안에는 적의 이동 속도를 늦추기 위해서입니다.
Controlled Pawn에서Get Actor Location을 사용하고,Branch와 연결한Return Value에서GetRandomReachablePointInRadius를 사용합니다.
다음 세팅을 사용하여GetRandomReachablePointInRadius의Radius를 변수로 승격합니다.
이미지를 클릭하면 최대 크기로 볼 수 있습니다.
- 변수 이름:PatrolRadius - 인스턴스 편집가능:활성화 - Patrol Radius(기본값):1000.0
그러면 적 캐릭터는 현재 위치에서 1,000유닛 이내의 랜덤 위치를 찾게 됩니다. 또한 Branch 노드를 사용하여 이동할 수 있는 랜덤 위치를 찾지 못하는 엣지 케이스를 처리합니다.
Random Location핀을 드래그하여Set Blackboard Value as Vector를 연결하고키를PatrolLocation이라는 변수로 승격합니다.
Set Blackboard Value as Vector노드를 하나 더 사용하고,Value는Get Actor Location에서 얻습니다.
이전 단계에 이어 아래와 같이 두 노드를 연결하여Finish Execute를Success를 체크합니다..적은 이동할 만한 랜덤 위치를 찾으면 블랙보드에 자신이 이동할 위치로 저장합니다. 이동할 만한 위치를 찾지 못하면 현재 위치를 사용하고 가만히 있다가 새로운 위치를 찾는 시도를 합니다. 제어되는 폰이 Enemy_Character가 아닌 엣지 케이스도 처리해야 합니다.
형변환(Cast)노드의Cast Failed핀에Finish Execute를 연결하고Success를 비활성화합니다.제어되는 폰이 Enemy_Character가 아닌 경우, 이 태스크는 성공하지 못한 것으로 판정되고 중단됩니다.
랜덤 순찰 탐색 태스크(Find Random Patrol Task)가 완성되었습니다. 다음 단계에는데코레이터(Decorator)를 자세히 살펴보고, 데코레이터를 조건식으로 사용하는 방법과 AI 컨트롤러(AI Controller) 구성에 활용하는 방법을 알아보겠습니다.
6 - AI 컨트롤러 구성
이 단계에는 최종 단계를 위한 준비 작업으로 AI 컨트롤러 안에서데코레이터(Decorator)를 구성하여비헤이비어 트리의 어떤 분기로 진입할지 결정해 보겠습니다.
콘텐츠 드로어(Content Drawer)에서Enemy_Controller블루프린트를 열어이벤트 On Possess노드를 추가합니다.
이벤트 On Possess에Run Behavior Tree노드를 추가하고BTAsset을BT_Enemy로 설정합니다. Run Behavior Tree는 AI 컨트롤러 클래스 블루프린트를 타깃으로 하는 컨텍스트 함수 호출로, 할당된비헤이비어 트리에셋을 실행할 수 있게 해 줍니다.
컴포넌트(Components)창에서+추가를 클릭하여AI 퍼셉션 컴포넌트(AIPerception Component)를 검색하고 추가합니다. AI 퍼셉션 컴포넌트는AI 퍼셉션 시스템(AI Perception System)에서 자극 리스너를 생성하고 사용자가 반응하도록 등록된 자극(여기서는 시각 사용 가능)을 수집하는 데 사용됩니다. 이 기능을 통해 AI가 플레이어를 보고 반응하도록 구성이 가능합니다.
AI 퍼셉션 컴포넌트의디테일(Details)패널에서AI 시야 구성(AI Sight Config)을 추가하고중립 탐지(Detect Neutrals)를 활성화합니다. 소속 감지(Detection by Affiliation)프로퍼티를 사용하면 같은 소속 팀원들과 함께 상대 팀원들을 공격하는 팀 기반 AI를 구성할 수 있습니다. 액터는 디폴트로 소속이 할당되지 않으며 중립으로 간주됩니다.
현재는 블루프린트를 통해 소속을 할당할 수 없으므로 플레이어를 찾아내려면 중립 탐지 플래그를 활성화해야 합니다. 여기서는 액터 태그 지정(Actor Tagging) 을 대신 사용하여 어떤 캐릭터가 플레이어인지 판단하고 AI 캐릭터가 플레이어로 태그 지정된 액터만 뒤쫓도록 구성합니다.
AIPerception의이벤트(Events)섹션에서타깃 퍼셉션 업데이트 시(On Target Perception Updated)옆의+표시를 클릭합니다.
그래프의타깃 퍼셉션 업데이트 시에서Actor Has Tag노드를 추가하여Tag를Player로 설정합니다.
Branch노드를 추가하여Condition을 아래와 같이 설정합니다. 여기서는 액터가 성공적으로 감지되었는지, 액터에 플레이어 태그가 있는지 확인합니다.
AIStimulus 분해 노드를 선택하고 디테일 패널에서 연결되지 않은 핀 숨김(Hide Unconnected Pins) 을 사용하여 위와 같이 그래프에서 연결되지 않은 핀을 모두 숨깁니다.
Branch의False에Set Timer by Event를 추가하고Time을4.0으로 설정합니다.
Time을 우클릭하여 변수로 승격한 후Line Of Sight Timer로 이름 짓습니다.
이 변수에 할당된 값은 AI가 플레이어를 추격하길 그만두고 어태치된 이벤트가 실행되기 전까지의 시간을 결정합니다.
Set Timer by Event의Return Value를 우클릭하고 변수로 승격하여EnemyTimer로 이름 짓습니다.
이렇게 하면핸들(Handle)을 통해 타이머에 대한 레퍼런스가 저장됩니다. 이 핸들은 스크립트를 통해 호출되어 자기 자신을 무효화하고 관련 이벤트를 모두 지움으로써 관련 이벤트가 실행되지 않도록 방지합니다. 나중에 Line of Sight Timer가 만료되기 전에 AI가 플레이어를 다시 발견하는 이벤트에서 사용할 수 있습니다. 그렇게 하면 AI가 플레이어를 시야에서 놓친 뒤 바로 추격을 포기하지 않도록 방지할 수 있습니다.
커스텀 이벤트(Custom Event)를 생성하여StartEnemyTimer로 이름 짓고Set Timer by Event의Event핀에 연결합니다.
우클릭하고Variables > AI아래의Get Blackboard노드를 추가합니다.
블랙보드에서Set Value as Bool과Set Value as Object를 사용하여 아래와 같이 연결합니다. 이렇게 하면 새로운 값으로 정의된블랙보드 키(Blackboard Key)를 업데이트할 수 있습니다.
Key Name을 둘 다 우클릭하여변수로 승격한 후 각각HasLineOfSight와EnemyActor로 이름 짓습니다.
블루프린트를컴파일(Compile)하고Key Name의디폴트값(Default Values)을 각각HasLineOfSight와EnemyActor로 설정합니다. 이미지를 클릭하면 최대 크기로 볼 수 있습니다.
Branch의True에서Get EnemyTimer를 사용하고Clear and Invalidate Timer by Handle에 연결합니다.
그러면 AI가 플레이어를 발견할 때부터 플레이어를 다시 시야에서 놓칠 때까지, 즉 새로운 Line Of Sight Timer가 시작될 때까지 Line Of Sight Timer를 초기화합니다.
이미지와 같이블랙보드노드,Set Value as및Key Name노드를 복사하여 붙여넣습니다.
Set Value as Bool노드에서Bool Value를 활성화하고 이미지와 같이 맨 왼쪽 On Target Perception Updated 액터(Actor)핀을Object Value로 드래그합니다. 그러면Has Line Of Sight의블랙보드 키 값(Blackboard Key Values)을True로,EnemyActor를 우리가 인지한 (플레이어일 경우에만 트리거되도록 구성했던)액터로 설정합니다.
컴파일을 클릭하여 컴파일하고 블루프린트를 닫습니다.
최종 그래프는 아래 비슷하게 보여야 합니다.
7 - 데코레이터와 최종 구성
이 마지막 섹션에서는 플레이어 캐릭터와 적 캐릭터 블루프린트의 일부 세팅을 조정합니다. 또한비헤이비어 트리에서 특정 조건에 따라 진입할 분기를 정해 줄데코레이터(Decorator)를 구성합니다.
콘텐츠 드로어(Content Drawer)에서콘텐츠(Content) > ThirdPersonBP > Blueprints경로의ThirdPersonCharacter블루프린트를 실행합니다.
디테일(Details)패널에서태그를 찾아 추가하고Player로 설정합니다. 이렇게 플레이어 태그를 설정 및 추가하면 AI는 이제 플레이어를 인지하고 반응할 수 있습니다.
AI폴더에서Enemy_Character블루프린트를 실행합니다.
디테일패널에서회전(Rotation)을 찾아컨트롤러 회전 요 사용(Use Controller Rotation Yaw)을 활성화합니다. 그러면 AI는비헤이비어 트리에서Rotate to Face BB Entry가 호출될 때 적절하게 회전할 수 있게 됩니다.
폰 옵션이 보이지 않나요? 툴바에서 클래스 디폴트(Class Defaults) 버튼을 클릭해야 할 수도 있습니다.
BT_Enemy를 실행하여Chase Player를 우클릭하고데코레이터 추가...(Add Decorator...)에서Blackboard를 선택합니다. 서브 노드설명
데코레이터(Decorator)
조건식이라고도 합니다. 이 노드는 다른 노드에 어태치되어 트리의 분기나 단일 노드의 실행 여부를 결정합니다.
서비스(Service)
이 노드는태스크(Task)및컴포짓(Composite)노드에 어태치하여 자신의 분기가 실행되는 동안 정의된 주기만큼 실행됩니다. 보통블랙보드의 확인 및 업데이트에 사용됩니다. 이 노드는 다른 비헤이비어 트리 시스템에서 전통적인 병렬(Parallel) 노드를 대체합니다.
여기서는블랙보드 데코레이터를 사용하여블랙보드 키값을 결정하고 이것이 유효한 경우 해당 분기를 실행할 수 있도록 구성합니다.
비헤이비어 트리에서 노드를 우클릭하면 다음과 같은 추가 기능을 제공하는 서브 노드를 추가할 수 있습니다.
추가된Blackboard Based Condition을 선택하여디테일패널에서 다음과 같이 설정합니다.
관찰자 중단(Observer aborts):Both
블랙보드 키(Blackboard Key):HasLineOfSIght
노드 이름(Node Name):Has Line of Sight?
HasLineOfSight값이Is Set(또는 true)인 경우Chase Player분기를 실행하게 하는 것입니다. Both로 설정된관찰자 중단은 할당한블랙보드 키가 변경될 때 자기 자신인Chase Player와 우선순위가 자신보다 낮은 태스크를 모두 중단하게 합니다. 즉,HasLineOfSight값이 변경되었으며 설정되지 않은 경우 자기 자신인Chase Player를 중단하고, 그 시점에 다음 분기인Patrol을 실행하는 것입니다. HasLineOfSight값이Is Set이 되면 관찰자는 우선순위가 낮은 태스크를 중단하면서Chase Player분기를 다시 실행될 수 있게 합니다.
컴파일(Compile)후비헤이비어 트리를 닫고 에디터에서플레이합니다.
최종 결과
이제 AI를 테스트해 봐도 좋습니다. AI는 플레이어를 발견하면 따라올 것입니다.
AI는 플레이어가 시야에서 보이지 않게 되어도 플레이어를 추격하며 시야를 확보하려 할 것입니다.Line Of Sight Timer값으로 입력한 시간이 지나면 AI는 추격을 포기하고 다시 순찰 상태로 돌아갑니다.
플레이 중에비헤이비어 트리가 작동하고, 서로 다른 분기 간의 전환이 이루어지는 것을 확인할 수 있습니다. 플레이 중에비헤이비어 트리안의 변수들을 지켜보며 AI가 현재 어떤 값을 갖고 있는지 알아볼 수도 있습니다.
8 - 직접 해 보기!
플레이어를 추격하다가 일정 시간 동안 시야에서 놓치면 다시 순찰로 돌아가는 AI 캐릭터가 생겼으니, 여기에 자신만의비헤이비어 트리로 다음과 같은 요소를 추가해 볼 수 있습니다!
비헤이비어 트리에서 두 개의Move To태스크에 선행태스크의 기능을 포함하는서비스를 새로 추가해 봅니다.
원래의비헤이비어 트리는 별도의태스크를 사용하여 이동 속도를 조정하고(플레이어를 추격할 때), 순찰할 랜덤 위치를 찾을 때는 이동 속도를 낮추었습니다(순찰할 때). 이것을서비스로 변환하여Move To태스크에 어태치해 봅니다.
힌트:서비스의 스크립트는 각태스크의 스크립트와 비슷하겠지만,이벤트 Receive Execute AI대신이벤트 Receive Activation AI를 사용해야 합니다. 이것들은서비스이기 때문에Finish Execute노드도 사용할 필요가 없습니다.
랜덤 위치를 순찰하는 대신순찰 경로 블루프린트(Patrol Path Blueprint)를 생성하여 AI가 왕복할 수 있는 벡터 값 변수의 배열을 추가해 봅니다.
힌트:배열 내에서의 순환으로 다음 항목을 얻어 AI가 특정 위치 사이를 왕복하게 하고, 배열 내 현재 항목을 베이스로블랙보드 키값PatrolLocation을 업데이트합니다.
AI가 플레이어를 시야에서 놓친 경우, 플레이어의 현재 위치가 아니라 마지막으로 보았던 플레이어의 위치로 이동하도록 만들어 봅니다.
힌트:Move To명령으로돌아서서 플레이어를 추격(Turning and Chasing the Player)하려면,EnemyActor대신 특정 위치를 지정해 줘야 합니다. 지금은EnemyActor의 위치, 즉 플레이어의 현재 위치를 얻도록 설정되어 있기 때문입니다.
AI가 플레이어에게 도달하면 공격하는 기능을 추가해 봅니다.
힌트:돌아서서 플레이어를 추격의백그라운드 태스크(Background Task)에 새컴포짓(Composite)노드를 추가합니다. AI가 플레이어에게 도달한 후에 공격 애니메이션을 갖춘태스크노드를 추가합니다