프로그래밍/Unity

Unity Behavior Tree 시스템 개요 - 1 ( Behavior Tree 란? )

DefineJH 2022. 6. 28. 21:13

분석이 끝나고 올리지 않으려 했는데 Behavior Tree를 검색하여 접속하는 사람이 많아 간단하게 시스템을 설명해보려 한다.

 

튜토리얼 11개 + 커스터마이징을 하였기 때문에 한 포스트에 다 설명하진 못할 것이다.

하지만 조금이라도 시스템을 파악할 수 있다면 많은 독자들에게 도움이 되리라 생각해 이를 올려볼 생각이다.

 

일단 Behavior Tree가 무엇인지부터 살펴보자.

Behavior Tree 란?

게임에서 Behavior Tree란 Behavior( 행동 ) 을 Tree 구조로 만들어 AI 의 행동을 이용해 제어하는 것이다.

 

행동을 트리로...? 약간 이해되지 않을 수 있다.

하지만 이렇게 생각해보자. Tree는 Node를 저장하는 하나의 컨테이너이다.

근데 자료구조를 공부하며 배운 Node란 과연 무엇일까?

 

int, float, string, char, double 등의 기본적인 타입을 저장하는 공간? 아니다.

Node에는 사용자가 정의할 수 있는, 혹은 미리 정의된 모든 타입이 저장될 수 있다.

 

행동 또한 사용자가 정의할 수 있는 하나의 타입이라 생각하면

Node에 행동을 저장하는 것도 그렇게 이상할 것이 없을 것이다.

 

Behavior Tree의 경우 Node 내부에 저장하는 것은 행동이라 말하는 코드 조각들을 저장하는 것이다.

 

이후, Behavior Tree의 실행은 Tree 자료구조의 DFS ( Depth First Search ) 순서에 따라 노드들을 실행시키면 된다.

DFS는 검색 알고리즘으로 찾고자 하는 노드가 아닐 경우 무조건 다음 Node로 이동이 가능하다. 

 

하지만 Behavior Tree에서의 노드들은 방문 시 무조건 저장된 코드 블럭을 실행한다.

그리고 실행 시 반환값이 존재하며 이에 따라 우선순위, 혹은 건너뛸 노드를 변경할 수 있다.

 

그리고 Behavior Tree에서의 노드들은 저장된 코드블럭의 역할에 따라 

Composite Node, Task(Action) Node, Decorator Node 의 카테고리로 나누어 지는데,

공통적으로 Node들은 Success , Failure , InProgress , Aborted 를 반환할 것이다.

  • Composite Node 
    • Sequence자식 노드들을 왼쪽->오른쪽 순서로 탐색하며 실행시킨다. 만약 자식 노드에서 Failure를 반환받으면 자식 노드의 탐색을 즉시 중지하고 부모에게 Failure를 반환한다. 모든 자식 노드가 Success를 반환하면 하위 SubTree의 자손 노드들을 방문하고 부모에게 Success를 반환. 한 자식 노드가 InProgress 반환 
    • Select자식 노드들을 왼쪽->오른쪽 순서로 탐색하며 실행시킨다. 만약 자식 노드에서 Success를 반환받으면 자식 노드의 탐색을 즉시 중지하고 부모에게 Success를 반환한다.
  • Decorator Node
    • While ( Conditional Loop )
    • If
    • Loop

정해진 조건에 따라 자식노드를 실행시키고 Success , Failure , InProgress 를 반환한다.

While, IF의 경우 조건을 만족한다면 자식노드를 실행시킨다.

Loop의 경우 자식 노드 실행 후, InProgress 반환. 특정 횟수 만족 시, Success 반환

  • Task(Action) Node

Behavior Tree 외부의 코드들을 호출하여 AI 의 특정 행동을 실행시키는 노드.

실행 결과에 따라 반환값이 달라진다.

 

실제 간단한 예제를 가지고 이를 이해해보자.

 

플레이어를 발견하기 위해 맵을 순찰하고 플레이어를 발견할 시 추적&공격을 하는 AI 가 있다 가정해보자.

이러한 AI를 Behavior Tree 로 구현하면 위와 같은 구조로 트리를 생성할 것이다.

필자가 직접 만든 플로우 차트로 이 Tree가 어떻게 동작하는지 살펴보자.

Case 1 : 플레이어를 발견하지 못하였을 때.

Root -> Selector -> IF 플레이어가 시야에 존재하지 않는가? -> True -> 순찰 진행 

 

Case 2 : 플레이어를 발견했지만 공격거리보다 멀 때.

Root -> Selector -> IF 플레이어가 시야에 존재하지 않는가? -> False -> Selector -> IF 공격 사정거리에 플레이어 존재? -> False -> 추격진행

 

Case 3 : 플레이어를 발견하였고 공격거리보다 가까울 때

Root -> Selector -> IF 플레이어가 시야에 존재하지 않는가? -> False -> Selector -> IF 공격 사정거리에 플레이어 존재? -> True -> Sequence -> 플레이어 공격 -> 2초 대기

 

위와 같이 실행될 것이다.

 

자 이제 이런 작동방식을 기반으로 다음 포스트부터 유니티서 Behavior Tree를 UI Builder를 사용해 구현해 볼 것이다.

 

 

 

 

 

 

반응형