비헤비어 트리는 그냥 겁나 간단하게 설명하자면 트리를 이용한 행동 결정 알고리즘이다.
비헤비어트리는 깊이 우선 탐색을 통해 현재 상황에서 가장 적절한 행동을 찾아가는 방식이다.
탐색 우선 순위는 오른쪽부터이다
비헤비어트리는 BlackBoard를 필요로 하는데 BlackBoard는 BehaviorTree가 로직을 실행하는 동안 필요한 정보를 저장하는 역할을 한다.
BehaviorTree와 BlackBoard는 언리얼엔진 콘텐츠 브라우저에서 마우스 오른쪽 클릭 -> AI(인공지능)에서 생성 가능하다.
언리얼 엔진의 비헤비어 트리는 크게 Composite, Decorator, Task, Service 노드로 구성된다.
Composite Node
Composite(Control Flow)
1) Selector : 자손 노드를 왼쪽부터 실행을 시도하고 그 중 하나가 실행에 성공하면 나머지 자손들의 실행을 멈춘다. 모든 자손이 실행에 실패하면 Selector의 작동이 실패한것. (if, else if, else 구조라 생각하면 편함)
위의 이미지를 예시로 들면 Selector 노드는 왼쪽의 자손 노드의 Dectorator노드를 먼저 실행을 시도하고 만약 그 노드가 True를 반환한다면 해당 노드를 실행한다. 만약 왼쪽의 노드가 false를 반환했다면 오른쪽의 자손 노드의 실행을 시도한다.
1) SetColor_Red_Task의 Decorator 노드 실행
2) Decorator 노드 결과가 True (여기서 false가 반환되면 다음 자손 노드를 실행시도)
3) SetColor_Red_Task 노드 실행
2) Sequence : 자손 노드를 왼쪽 부터 자손 노드가 실행에 실패하거나 모든 자손 노드를 실행할때까지 자손 노드를 실행 시도. 모든 자손 노드가 실행에 성공해야 Sequence 노드가 작동에 성공. (반복문 + 조건문 + break 라고 생각하면 편함)
위의 이미지를 예시로 설명하자면 자손 노드중 가장 왼쪽 노드를 실행하고 해당 노드가 실행에 성공하면 그 다음 자손 노드를 실행한다.
1) SetColor_Default_Task 노드 실행 시도
2) 성공 ( 여기서 만약 실패 하는 경우 다음 자손 노드를 실행하지 않고 Sequence 노드 실행 종료(실패 반환) )
3) Jump_Task 실행 시도
4) 성공
5) Sequence 노드 실행 완료(성공 반환)
3) Simple Parallel : 전체 트리 수행과 동시에 특정 Task노드를 동시 실행
(걷기, 뛰기, 엎드리기, 등의 이동 결정 트리과 사격을 동시에 진행)
보라색 연결 부분에 동시에 실행할 "Task" 노드를 연결 하면 회색 부분에 연결된 비헤비어 트리와 동시 실행
Decorator Node
Decorator 노드는 조건문의 조건절에 해당하는 부분이다.
(C 스타일 언어 if 문에서 ( )안의 조건)
위 이미지의 두 Decorator 노드는 블랙보드에 저장된 Distance 변수를 400에 비교하는 Decorator 노드들이다.
위 이미지에서 만약 Distance값이 400보다 높으면 SetColor_Red_Tast가 실행되고 400보다 낮으면 Sequence노드가 실행된다.
Service Node
Composite 노드에 붙어 해당 Composite 노드가 실행될때 설정된 실행 빈도에 따라 실행. 주로 상태 업데이트나 속도조절 유불리 판단 같은 작업에 쓰임
위 이미지에서는 Update에서 거리(Distance)를 Selector 노드가 실행될때마다 업데이트를 하고 있다.
그 아래 이미지에서 Interval은 해당 서비스 노드의 실행주기를 설정하는 부분이다
Task Node
트리의 말단 부분으로 이름 그대로 작업(이동, 공격, 등등)을 수행하는 노드다.
Task 노드는 Finish Execute 노드를 통하여 해당 Task 노드의 실행 성공/실패 여부를 반환한다.(Sequence 노드 등에서 활용, Sequnce노드 설명 다시 확인)
위 이미지는 이 게시물에서 예시로 사용중인 예제 Behavior Tree의 전체 모습이다.
이를 설명하자면 매 tick 마다 Update 서비스 노드를 통하여 Distance(두 객체 사이의 거리)를 업데이트하고 이 Distance 변수를 Selector 노드와 Decorator 노드를 이용하여 거리가 400보다 크면 빨간색으로 컬러를 변경하고 400보다 거리가 짧으면 Sequence노드를 이용하여 색을 기본 색으로 바꾸면서 점프를 수행한다. 아래의 동영상은 이 비헤비어 트리를 이용하여 작동하는 객체를 보여준다.
https://drive.google.com/file/d/1xTUT6ixToxnUTUUneEoZoT6i6y9HvneG/view?usp=sharing
TestBT.zip
drive.google.com
이 파일은 위 동영상의 예제 프로젝트이다. 이 게시물을 보면서 참고 하면 좋을것같다.
아 버전은 4.22.3 버전을 사용했다. 혹시나 그냥 언리얼 프로젝트 아이콘만을 실행하려는데 실행이 안된다면 언리얼 프로젝트를 오른쪽 클릭하여 Generate Visual Studio Project Files를 눌러서 비주얼 스튜디오 파일을 재생성한다음 비쥬얼 스튜디오 빌드를 이용해주기를 바란다. 혹은 버전을 현재 설치된 버전에 맞게 프로젝트 버전을 변경해주길 바란다.
위 예제 프로젝트를 제작하는 과정을 통해 대충 간단하게 실사용법을 보여주고자 한다.
1. 기본적인 셋팅
0) 기본 3인칭 예제 프로젝트를 이용
1) 비헤비어트리, 블랙보드 생성
콘텐츠 브라우져에서 마우스 오른쪽 클릭 -> 인공지능-> 블랙보드, 비헤비어트리 생성
일단 난 대충 HelloBT와 HelloBB라고 대충 이름 지었다.
HelloBT(생성한 비헤비어트리)를 실행하여 블랙보드를 할당시켜준다.
블랙보드에서 변수를 추가하는 방법은 아래와 같이 HelloBB 블랙보드 편집창을 열고 새키를 추가하면 된다.
여기서 Distance 라는 Key Name을 가지는 float 변수를 생성하길 바란다.
2) AIController 생성
블루프린트 생성 -> 검색에서 AIController 검색 -> 선택
(일단 난 AICon이라고 대충 이름 지음)
AICon을 실행하고
위 이미지와 같이 BeginPlay 이벤트에 Run Behavior Tree라는 노드를 생성하고 BTAsset을 방금 만든 HelloBT로 설정한다. 이 설정은 AICon이 사용할 비헤비어트리를 HelloBT로 설정을 한것이다. 이 설정을 통해 AICon을 컨트롤러로 가지는 모든 폰들은 HelloBT로 인해 지식/규칙 인공지능을 가지게 된다.
3) 비헤비어트리를 탑제할 Pawn(Charactor) 생성
ThirdPersonCharacter를 찾아서 복사 -> 대충 이름 AIPawn으로 붙여넣기
AIPawn을 열고 위 이미지와 같이 이벤트들을 만들어준다.
(이것도 못 따라서 못 만들겠다면 아직 비헤비어 트리를 다룰 상황이 아니라고 생각한다)
###매우 중요!!!###
AIPawn의 클래스 디폴트(Class Default)에서 Pawn 카테고리 AI Controller Class를 방금 만든 AICon으로 설정한다.
이 설정은 해당 Pawn을 조정하는 Controller를 AICon로 설정하는 것이다. (기본은 디폴트 AI Controller로 설정되있다)
2. 비헤비어트리 편집
이번 파트에선 위에서 보인 영상처럼 4미터 이내에 플레이어 캐릭터가 다가오면 색을 바꾸면서 점프를 하는 매우 간단한 AI를 만드는 과정을 보여주려고 한다
1) 플레이어 캐릭터와의 거리 인식 : Service Node의 활용
먼저 서비스를 새로 생성한다. 위 이미지와 같이 비헤비어트리 편집창을 키면 상단에 생성 버튼이 친절하게 있다.
BTService_BluePrintBase를 이용하여 신규 Service 노드 생성
아마 새로 생성한 서비스 노드의 편집차이 열려있을것이다. 신규 서비스 노드는 현재 열려있는 비헤비어트리의 위치에 생성되 있을것이다. 이를 Update 라고 이름을 변경하자
서비스 노드는 기본적으로 Receive Tick 이벤트를 생성한다. ( == 난 이걸 씀)
이 서비스 노드가 비헤비어트리에서 호출됐을때 Receive Tick 노드를 통하여 서비스 노드의 코드를 실행시킨다.
Owner Actor는 이 노드가 실행되는 비헤비어트리를 소유하고 있는 AI Controller이다. (이 예제 프로젝트에선 AICon)
AI 컨트롤러에 접근이 가능하기 때문에 이 비헤비어트리가 사용될 Pawn에도 접근이 가능하다. 위 이미지 참고
위 구조는 모든 서비스 노드의 기본 형태라고 생각해도 좋다. 물론 이 방법만 있는것은 아니다 예를 들어 아래의 이미지 처럼 블랙보드에서 이 비헤비어트리가 사용되는 Pawn에 접근하는 방법도 있다.
이 글을 쓰고 있는 인간은 두 방법중 첫번째 이미지와 같은 방법을 주로 사용했다.
(뭐가 더 최적화 된 방법이고 좋은 방법인지는 모르지만 그냥 위에꺼가 익숙해서 그냥 아무 생각없이 쓰고 있다)
위 이미지를 보면 블랙보드에 어떻게 접근하는지도 보여주고 있다. 블랙보드는 Pawn, Controller 둘다에서 접근 가능하다. 블랙보드는 String name 값을 Key 값으로 가지는 테이블이라고 생각하면된다
위 이미지는 이 예제에서 구현된 Update 노드의 전체 모습이다. Update 노드의 역할은 AIPawn과 Target(AIPawn에서 설정)과의 거리를 블랙보드에 업데이트 해주는 역할이다.
블랙보드 변수의 업데이트는 Set Value as [변수타입] 함수를 이용한다.
Key Name을 통해 블랙보드에 미리 생성한 변수에 접근하고 Value값을 통해 그 값을 업데이트 한다.
2) Task Node
서비스 노드를 만들었던것 처럼 테스크 노드를 생성하고 SetColor_Red_Task라고 이름 지어보자
Task 노드는 Receive Execute 이벤트를 이용하여 노드 호출을 수행한다.
Pawn에 접근하는 방법은 Service노드와 이벤트만 다를뿐 같은 방법들을 사용한다.
Set Color Red 함수(이벤트)는 AIPawn에서 구현했고 그걸 SetColor_Red_Task가 호출될때 실행하도록 했다.
위의 SetColor_Red_Task를 참고하여 Jump_Task와 SetColor_Blue_Task를 만들자
(SetMaterial 함수의
3) 거리 판단 : Decorator Node
지금까지 만든 노드들을 이용하여 "4m보다 멀면 빨간색, 4m보다 가까우면 파란색으로 변하면서 점프"를 하는 AI에 맞게 트리를 구성해봤다. 하지만 트리는 "4m보다 멀면", "4m보다 가까우면" 과 같은 조건절이 없다. 만약 이 트리를 실행을한다면 왼쪽부터 우선순위를 가지는 비헤비어트리의 특성에 따라서 어떠한 조건에서든 빨간색으로만 변하기만 할것이다.
Decorator 노드는 앞서 만든 Service노드나 Task 노드처럼 하나의 노드를 생성하여 만들수도 있지다 하지만 이 트리에서 필요한 기능은 그저 블랙보드 변수의 크기 비교일 뿐이다.
따라서 위 이미지와 같이 Decorator 노드를 붙일 노드에 오른쪽 클릭 -> 데코레이터 추가 -> Blackboard를 선택한다.
데코레이터 노드를 클릭하면 화면 오른쪽에서 설정을 할수있다.
Key Query는 비교문을 설정
Key Value는 비교할 기준 숫자를 설정(4미터지만 언리얼엔진은 기본 거리 유닛이 Cm이기 때문에 400으로 설정)
BlackBoard Key는 비교할 BlackBoard 변수를 선택할수있다.
이를 이용하여 트리를 완성하면
이러한 모양과 함께 "4m보다 멀면 빨간색, 4m보다 가까우면 파란색으로 변하면서 점프"를 하는 비헤비어트리가 완성됐다.
출처 : 내 뇌