정교한 AI는 게임의 완성도와 직결된다.
예를 들어 슈팅 게임을 만든다고 했을 때 AI의 움직임이 매우 부자연스럽거나 혹은 플레이어를 만나도 멀뚱멀뚱하면 게임의 재미가 떨어질 것이고, 또는 오히려 너무 반응 속도가 빨라서 마주치자마자 플레이어를 죽여버리는 경우 역시 좋지 않을 것이다.
따라서 상황에 맞게 적절하게 움직이고, 행동하는 AI를 만드는 것은 중요하다.
언리얼 엔진에서 이러한 AI 기능을 구현할 수 있는 것은 블랙보드(blackboard)와 비헤이비어 트리(behavior tree) 이다.
블랙보드는 AI 동작에 필요한 여러 데이터들을 저장하는 저장소라고 생각하면 된다. Behavior Tree (이하 BT)에 연결해서 이 데이터를 읽고, 수정하고, 초기화할 수 있다.
BT는 문자 그대로 트리 형태의 그래프이다.
다양한 상황에서 어떤 행동을 할 지에 대한 내용들을 조건을 분기하여 작성한다.
모든 트리에는 루트 노드가 존재하고, 항상 이 루트 노드에서 시작한다.
Composites are a form of flow control and determine how the child branches that are connected to them execute.
컴포짓 노드는 실행 흐름을 제어할 수 있다.
selector의 왼쪽 서브노드부터 차례대로 수행하며, 그 중 실행에 성공한 서브노드가 발생하면 실행을 종료한다.
등록된 서브 노드들을 왼쪽에서 오른쪽으로 차례대로 수행한다.
하나의 서브노드가 성공하면 바로 실행을 종료하는 selector와는 달리 sequence 노드는 실패하는 노드가 발생할 때까지 계속해서 서브 노드들을 수행해 나간다. 모든 서브노드가 성공해야 전체 sequence가 성공 처리된다.
Simple Parallel 노드는 두 개의 연결이 존재하고, 이 두 개의 연결에 붙은 태스크가 동시에 수행된다. 메인 태스크와 서브 태스크가 존재하고, 메인 태스크가 끝나면 서브 태스크를 종료할지, 서브 태스크까지 종료되기를 기다릴지를 설정할 수 있다.
이 노드를 실행할지의 여부를 판단할 수 있다. 특정 값이 set 되었는지, 또는 루프 설정을 할 수 있다.
트리가 진행됨에 따라 백그라운드에서 실행될 것들을 정의할 수 있다. 그 브랜치가 활성화되면 실행되며, 태스크와는 다르게 어떤 값을 반환하지는 못하기 때문에 실행 플로우에 영향을 미치지는 않는다.
보통 일정한 주기로 값을 업데이트해야 하는 상황에서 이 Service 중에 TickNode
함수가 주로 사용된다.
함수의 종류에는 OnBecomeRelevant
, OnCeaseRelevant
, TickNode
등이 있다.
태스크 노드는 BT의 리프 노드이며, 블랙보드에 저장된 값을 변경하거나 하는 등의 특정한 액션을 수행한다.
Move To, Wait 등 기본적인 함수들이 내장되어 있으며, 사용자가 직접 클래스를 만들 수도 있다.