[언리얼엔진] 비헤이비어 트리 개요

    언리언 엘진의 비헤이비어 트리 개념과 일반적인 비헤이비어 트리와의 차이점을 알아보자

    언리얼 엔진 5(언리얼 엔진)에서 캐릭터에 사용할 인공 지능(AI)을 생성하는 방법은 다양하다. 블루프린트 비주얼 스크립팅(Blueprint Visual Scripting)을 사용하면 캐릭터가 애니메이션을 재생하거나, 특정 위치로 이동하거나, 충돌에 반응하는 등 '무언가를 하도록' 지시할 수 있다. AI 캐릭터가 스스로 생각하고 결정을 내리도록 하려면 비헤이비어 트리(Behavior Tree)를 사용해보자. 아래 비헤이비어 트리는 AI 캐릭터가 순찰과 플레이어 추격 사이에서 행동을 전환하는 예시다.

    비헤이비어 트리 기본

    비헤이비어 트리는 블루프린트와 유사한 시각적 방식으로 생성된다. 기능이 탑재된 다양한 노드를 추가하고 연결하여 비헤이비어 트리 그래프(Behavior Tree Graph)를 만드는 방식이다. 비헤이비어 트리가 로직을 실행하는 한편, 비헤이비어 트리가 결정을 내리는 데 필요한 정보인 블랙보드 키(Blackboard Key) 는 블랙보드(Blackboard) 라는 별도의 에셋에 저장된다. 일반적인 워크플로는 블랙보드를 생성하고, 블랙보드 키를 추가한 다음, 블랙보드 에셋을 사용하는 비헤이비어 트리를 생성한다. 블랙보드는 아래에서처럼 비헤이비어 트리에 할당된다.

    언리얼 엔진의 비헤이비어 트리는 왼쪽에서 오른쪽, 위에서 아래 순서로 로직을 실행한다. 실행 순서는 그래프에 배치된 노드의 우측 상단에 표시되는 숫자로 확인할 수 있다. 아래 이미지의 비헤이비어 트리 그래프에서 가장 왼쪽의 샘플 분기에 연결된 노드들은 블랙보드 키 HasLineOfSight 가 설정된 경우 AI가 플레이어를 추격하도록 지시한다.

    파란색 노드는 데코레이터(Decorator)이다. 다른 비헤이비어 트리 시스템의 조건문에 해당한다. 데코레이터는 컴포짓(Composite)노드에 어태치되어 블랙보드 키가 True인지 검증하는데 사용된다. 이를 통해 나머지 분기를 실행할지 결정된다. 보라색 노드는 태스크(Task) 노드이며, AI가 수행할 수 있는 액션이다.

    비헤이비어 트리와 로직을 생성했다면 트리를 실행해보자. 보통은 폰(Pawn) 또는 캐릭터거나 다른 엔티티인 AI의 '바디'가 있고, 거기 연결된 AI 컨트롤러(AI Controller)를 사용해서 폰을 제어하고 액션을 지시한다. 비헤이비어 트리를 실행하는 것도 액션 중 하나다. 아래는 폰에 커스텀 AI 컨트롤러 클래스를 할당했다.

    그리고 AI 컨트롤러에서는 컨트롤러가 폰에 '빙의'할 때 비헤이비어 트리를 실행한다.

    폰이 환경을 탐색하게 하려면 내비메시 바운드 볼륨(Nav Mesh Bounds Volume) 을 레벨에 추가해야 한다.

    언리얼 엔진 비헤이비어 트리의 차별점

    이벤트 주도형 비헤이비어 트리

    언리얼 엔진 비헤이비어 트리가 다른 비헤이비어 트리 시스템과 다른 점 중 하나는 이벤트로 주도되기 때문에 프레임마다 불필요한 작업이 수행되지 않는다는 점이다. 관련 변경 사항이 발생했는지 지속적으로 확인하는 대신에, 비헤이비어 트리는 트리 내 변경 사항을 트리거하는 데 사용할 수 있는 '이벤트'를 수동적으로 리스닝한다. 아래는 블랙보드 키 HasLineOfSight를 업데이트하는 데 이벤트가 사용되었다.

    이벤트 주도형 아키텍처가 있으면 퍼포먼스와 디버깅이 모두 개선된다. 그러나 이러한 개선 사항을 최대한 활용하기 위해서는 언리얼 엔진 비헤이비어 트리의 나머지 차이점도 이해하여 비헤이비어 트리의 구조를 적절하게 구성해야 한다. 코드가 매 틱마다 전체 트리를 반복작업할 필요가 없기 때문에 퍼포먼스가 훨씬 뛰어나다. 개념적으로는, 도착했는지 계속해서 묻지 않고 도착할 때까지 쉬다가 도착했다는 알림을 받는 것과 동일하다.

    비헤이비어 트리의 실행 히스토리를 한 단계씩 앞뒤로 이동하면서 비헤이비어를 시각적으로 디버깅하는 경우, 연관성이 있는 변경 사항만 히스토리에 표시하고 무관한 사항은 표시하지 않는 것이 이상적이다. 언리얼 엔진의 이벤트 주도형 구현 방식에서는 트리를 반복작업하여 이전과 동일한 비헤이비어를 선택하는 연관성 낮은 단계를 필터로 걸러낼 필요가 없다. 추가적인 반복 작업이 애초에 발생하지 않기 때문, 대신에 트리 내에서의 실행 위치 또는 블랙보드 값의 변경만 고려하면 되고, 이러한 차이점을 표시하는 것은 쉽다.

    조건문이 리프 노드가 아님

    비헤이비어 트리 표준 모델에서의 조건문은 '태스크' 리프 노드로, 성공이나 실패 이외에는 아무것도 하지 않는다. 물론 전통적인 조건문 태스크를 만들지 못할 이유는 없지만, 조건문에는 데코레이터(Decorator)를 사용하는 것을 권장함
    조건문을 태스크가 아닌 데코레이터로 만들면 다음과 같은 이점이 있다.

    • 조건문 데코레이터는 비헤이비어 트리 UI를 보다 직관적이고 읽기 쉽게 만들어 준다.
    • 모든 리프가 액션 태스크이므로 트리를 통해 실제 어떤 액션이 지시되는지 알기가 더 쉽다.

    조건문은 자신이 제어하는 서브트리의 루트에 있으므로 조건이 충족되지 않은 경우 트리의 어떤 부분이 '닫혔는지' 바로 알 수 있다. 또한 모든 리프가 액션 태스크이므로 실제 액션을 알기가 더 쉽다. 기존에는 조건문이 리프 사이에 있으므로 어떤 리프가 조건문이고 어떤 리프가 액션인지 알아내기 어려웠다.

    위 비헤이비어 트리 섹션에서는 'Close Enough'와 블랙보드 데코레이터가 시퀀스 노드의 자손이 실행되는 것을 방지한다. 조건문 데코레이터의 또 다른 이점은 트리 내 중요 노드에서 이벤트를 기다리는 관찰자 역할로 만들기 쉽다는 것이다. 트리의 이벤트 주도형 속성을 최대한 활용하는 데 매우 중요하다.

    동시 발생 비헤이비어

    표준적인 비헤이비어 트리는 보통 병렬 컴포짓 노드를 사용하여 동시 발생 행동을 처리하며, 이 병렬 노드는 모든 자손에서 동시에 실행되기 시작한다. 자손 트리 중 하나 이상이 종료되었을 때 어떤 액션을 취할지는 (원하는 행동에 따라) 특수 규칙으로 결정한다.

    언리얼 엔진 비헤이비어 트리는 복잡한 병렬 노드 대신 단순 병렬(Simple Parallel) 노드, 서비스(Services)라는 특수 노드, 데코레이터의 관찰자 중단(Observer Aborts) 프로퍼티를 사용하여 동일한 유형의 행동을 달성한다.

    단순 병렬 노드

    단순 병렬 노드는 자손을 두 개만 갖는다. 한 자손은 반드시 단일 태스크 노드여야 하며(데코레이터 선택 가능), 나머지 자손은 완전한 서브트리일 수 있다. 단순 병렬 노드는 'A를 수행하는 동안 B도 수행한다'로 생각하면 된다. 기본적으로 A는 주요 태스크이고, B는 A가 완료되기까지 기다리는 도중의 부가 태스크 또는 필러 태스크다.

    부가 태스크(태스크 B)를 처리하는 방법에는 몇 가지 옵션이 있지만, 노드 개념은 전통적인 병렬 노드에 비해 비교적 단순하다. 그러면서도 병렬 노드가 사용되는 일반적인 경우를 대부분 지원한다. 단순 병렬 노드를 사용하면 이벤트 주도형 최적화를 활용하기 쉽지만, 완전 병렬 노드는 최적화하기 훨씬 까다롭다.

    서비스

    서비스는 셀렉터, 시퀀스, 단순 병렬 등 모든 컴포짓 노드와 연관되는 특수 노드로, 지정된 시간(초)마다 콜백을 등록하고 주기적으로 발생시킬 필요가 있는 다양한 유형의 업데이트를 수행한다. 예를 들어 AI 폰이 현재의 적을 쫓는 비헤이비어 트리를 정상적으로 따라가는 동안 어느 적이 최적의 대상인지 결정하기 위해 서비스를 사용할 수 있다. 서비스는 자신이 추가된 컴포짓 노드의 서브트리에 실행이 머물러 있는 동안만 활성화된다.

    관찰자 중단

    표준 병렬 노드의 흔한 용도 중 하나는 조건을 지속적으로 확인하여 요구 조건이 False가 되는 경우 태스크를 중단하는 것이다.

    예를 들어 '쉭쉭거리기' 와 '달려들기' 시퀀스를 수행하는 고양이가 있다면, 쥐가 쥐구멍으로 도망치는 순간 즉시 포기하도록 하는 것이 좋다. 병렬 노드로는 쥐에게 달려들 수 있는지 확인하는 자손과 시퀀스가 수행할 자손을 가질 수 있다. 언리얼 엔진 비헤이비어 트리는 이벤트 주도형이므로 이렇게 하는 대신에 조건문 데코레이터에서 해당 값을 관찰하게 하고 필요시 중단시키는 방식으로 처리한다. 이 예시에서는 '쥐에게 달려들 수 있는가?'를 들 수 있다. 이 경우, 시퀀스의 데코레이터에서 '관찰자 중단'을 '셀프(Self)'로 설정하면 된다.

    동시 발생 비헤이비어에 대한 언리얼 엔진 접근법의 장점

    언리얼 엔진에서 동시 발생 비헤이비어를 처리하는 방법에는 다음과 같은 세 가지 주요 장점이 있다.

    • 명료성 - 서비스와 단순 병렬 노드를 사용하여 읽기 쉽고 이해하기 쉬운 단순한 트리를 만들 수 있다.
    • 쉬운 디버깅 - 그래프가 명료하므로 디버깅도 쉽다. 또한 동시 실행 경로가 더 적어서 지금 어떤 것이 실행되고 있는지 파악하기 더 쉽다.
    • 더 쉬운 최적화 - 이벤트 주도형 그래프는 동시에 실행되는 서브트리가 많지 않다면 최적화하기 더 쉽다.

    문서

    https://docs.unrealengine.com/5.2/ko/behavior-tree-in-unreal-engine---overview/

    반응형

    댓글

    Designed by JB FACTORY