icon
11장 : 고급 주제와 최신 기술

AI와 행동 트리


이전 절에서 우리는 언리얼 에디터를 확장하고 커스텀 툴을 개발하여 개발 워크플로우를 최적화하는 방법에 대해 알아보았습니다. 이제 게임 개발의 또 다른 복잡하지만 매력적인 고급 주제인 인공지능(AI), 특히 언리얼 엔진에서 널리 사용되는 행동 트리(Behavior Tree) 에 대해 다뤄볼 차례입니다. 잘 만들어진 AI는 게임에 생동감을 불어넣고 플레이어에게 도전적이며 몰입감 있는 경험을 제공합니다.

이번 절에서는 언리얼 엔진의 AI 시스템 기본 개념부터 시작하여, 행동 트리의 구조와 작동 방식, 그리고 효과적인 행동 트리 설계를 위한 모범 사례까지 자세히 살펴보겠습니다.


게임 AI의 기본 개념

게임 AI는 플레이어의 행동에 반응하고, 게임 세계 내에서 지능적인 것처럼 보이는 결정을 내리도록 설계된 비플레이어 캐릭터(NPC)의 동작을 제어하는 시스템을 의미합니다.

  • NPC (Non-Player Character): 플레이어가 아닌 캐릭터로, AI에 의해 제어됩니다.
  • 지능: 게임 AI에서 "지능"은 실제 인간의 지능과는 다르며, 미리 정의된 규칙, 알고리즘, 데이터에 기반하여 목표를 달성하는 능력을 의미합니다.
  • 의사 결정: AI는 환경 분석, 목표 설정, 행동 계획 수립 등의 과정을 통해 의사 결정을 내립니다.

언리얼 엔진은 AI를 구현하기 위한 다양한 내장 기능을 제공하며, 그 중심에는 AI 컨트롤러(AI Controller)행동 트리(Behavior Tree), 그리고 블랙보드(Blackboard) 가 있습니다.


AI 컨트롤러 (AI Controller)

모든 AI 캐릭터는 자신의 행동을 제어하는 AI 컨트롤러를 가집니다. AI 컨트롤러는 플레이어의 PlayerController와 유사하게, 해당 캐릭터의 인지(Perception), 의사 결정(Decision Making), 행동(Action Execution) 로직을 담당합니다.

  • 설정: Character 블루프린트나 C++ 클래스에서 AI Controller Class 속성을 설정하여 해당 캐릭터가 사용할 AI 컨트롤러를 지정합니다.
  • 주요 기능
    • Perception (인지): AIPerceptionComponent를 사용하여 시각(Sight), 청각(Hearing), 촉각(Damage) 등 다양한 방식으로 게임 세계를 인지합니다.
    • Movement (이동): MoveToActor 또는 MoveToLocation 함수를 사용하여 내비게이션 시스템(Navigation Mesh)을 통해 캐릭터를 이동시킵니다.
    • Behavior (행동): 행동 트리를 실행하여 캐릭터의 복잡한 행동을 제어합니다.

내비게이션 메시 (Navigation Mesh)

AI 캐릭터가 게임 월드 내에서 이동할 수 있는 영역을 정의하는 시스템입니다. 언리얼 엔진은 Nav Mesh Bounds Volume을 사용하여 내비게이션 메시를 자동으로 생성합니다.

  • 작동 방식: 에디터에서 P 키를 누르면 내비게이션 메시(기본적으로 녹색)가 시각화됩니다. AI는 이 메시 위에서만 이동 경로를 계산할 수 있습니다.
  • 활용: AI가 복잡한 환경에서 장애물을 회피하며 목표 지점까지 도달할 수 있도록 해줍니다.

행동 트리 (Behavior Tree)

행동 트리는 AI의 의사 결정을 계층적이고 유연하게 구성하는 데 사용되는 트리(Tree) 구조의 시스템입니다. 특히 복잡한 AI 행동을 시각적으로 설계하고 디버깅하기에 매우 효과적입니다.

행동 트리의 핵심 구성 요소

  • Root (루트): 행동 트리의 시작점. 항상 하나만 존재합니다.
  • Composites (복합 노드): 자식 노드들의 실행 흐름을 제어합니다.
    • Selector (선택자): 자식 노드를 왼쪽에서 오른쪽으로 순서대로 시도하며, 성공하는 첫 번째 자식을 실행합니다. 하나라도 성공하면 자신도 성공하고, 모든 자식이 실패하면 자신도 실패합니다. (예: "싸울 수 있다면 싸우고, 아니면 도망쳐라")
    • Sequence (시퀀스): 자식 노드를 왼쪽에서 오른쪽으로 순서대로 실행하며, 모든 자식이 성공해야 자신도 성공합니다. 하나라도 실패하면 자신도 실패합니다. (예: "목표를 찾고, 경로를 계산하고, 이동한 다음, 공격해라")
    • Simple Parallel (단순 병렬): 주 작업(Main Task)과 부 작업(Auxiliary Task)을 동시에 실행합니다.
  • Decorators (데코레이터 / 조건부 노드): 자식 노드의 실행 여부를 결정하는 조건부 로직을 추가합니다.
    • Blackboard-based Decorator: 블랙보드 값을 기반으로 조건을 검사합니다.
    • Is Player Closer: 플레이어와의 거리를 기준으로 조건을 검사합니다.
    • Cooldown: 특정 행동의 재사용 대기시간을 설정합니다.
    • Force Success/Fail: 자식 노드의 성공/실패 여부를 강제합니다.
  • Services (서비스): 특정 주기마다 실행되는 노드로, 블랙보드 값을 업데이트하거나 환경을 모니터링하는 데 사용됩니다.
    • Tick Interval을 설정하여 서비스가 실행될 간격을 제어합니다. (예: "0.5초마다 플레이어 위치를 확인하여 블랙보드에 기록")
  • Tasks (작업 노드): AI가 실제로 수행하는 가장 작은 단위의 행동입니다.
    • Move To: 특정 위치나 액터로 이동합니다.
    • Wait: 일정 시간 동안 대기합니다.
    • Play Animation: 애니메이션을 재생합니다.
    • Run EQS: 환경 쿼리 시스템(EQS)을 실행하여 최적의 위치를 찾습니다.
    • Custom Task (사용자 정의 작업): 블루프린트나 C++로 직접 커스텀 작업을 구현할 수 있습니다. (예: "총 발사", "스킬 사용")

블랙보드 (Blackboard)

블랙보드는 행동 트리와 함께 사용되는 AI 데이터 저장소입니다. AI 컨트롤러가 게임 세계에서 인지하거나 계산한 중요한 정보(예: 플레이어 위치, 목표 액터, 경계 상태)를 저장하고, 행동 트리의 각 노드가 이 정보에 접근하여 의사 결정을 내리는 데 사용됩니다.

  • 키-값 쌍: FBlackboardData 에셋으로 정의되며, 문자열 와 특정 타입(Vector, Object, Bool 등)의 으로 구성됩니다.
  • 액세스: 행동 트리 내의 데코레이터, 서비스, 작업 노드는 모두 블랙보드 키를 참조하여 값을 읽거나 쓸 수 있습니다.
  • 장점: AI 로직과 데이터 관리 부분을 분리하여 재사용성과 가독성을 높입니다.

행동 트리 설계 및 구현 모범 사례

계층적 설계

  • 모듈성: 거대한 단일 행동 트리보다는, 작은 행동 트리들을 만들고 Run Behavior 작업을 통해 다른 행동 트리를 서브 트리(Subtree)처럼 호출하도록 합니다. 이는 재사용성을 높이고 관리하기 쉽게 만듭니다.
  • 추상화: 상위 레벨의 노드는 "목표를 달성하라"와 같은 추상적인 행동을 정의하고, 하위 레벨 노드에서 이를 구체적인 작업으로 분해합니다.

블랙보드 활용

  • 중앙 집중식 데이터: 모든 AI 관련 데이터를 블랙보드에 집중시켜 관리합니다.
  • 명확한 키 정의: 블랙보드 키의 이름을 명확하게 정의하여 어떤 정보를 저장하는지 쉽게 알 수 있도록 합니다.
  • 데이터 타입 일치: 키에 저장되는 데이터 타입이 일치하도록 주의합니다.

데코레이터의 현명한 사용

  • 조건부 실행: 데코레이터는 불필요한 행동 트리의 순회를 막아 성능을 향상시키고 로직을 명확하게 합니다.
  • 재평가(Observer Aborts): 데코레이터의 Observer Aborts 설정을 통해 조건이 변경될 때 현재 실행 중인 행동 트리 브랜치를 중단하고 재평가할지 결정합니다. 이는 AI의 반응성을 높이는 데 중요합니다.
    • None: 조건이 변경되어도 현재 브랜치 중단 안함.
    • Self: 이 데코레이터가 붙은 노드만 재평가.
    • Lower Priority: 현재 실행 중인 브랜치보다 우선순위가 낮은 브랜치만 재평가.
    • Both: 현재 브랜치와 낮은 우선순위 브랜치 모두 재평가.

서비스 활용

  • 지속적인 모니터링: 특정 주기마다 환경을 감지하거나 블랙보드 값을 업데이트해야 할 때 서비스를 사용합니다. (예: "플레이어가 시야 내에 있는지 주기적으로 확인")
  • 경량화: 서비스는 자주 실행될 수 있으므로, 내부 로직은 최대한 가볍게 유지해야 합니다. 무거운 계산은 다른 곳으로 오프로드하는 것을 고려합니다.

사용자 정의 작업 (Custom Tasks)

  • 재사용 가능한 행동: 블루프린트나 C++로 사용자 정의 작업을 만들어 복잡하거나 특정 게임 시스템과 연동되는 행동을 캡슐화합니다.
  • 명확한 입출력: 커스텀 작업은 명확한 입력(블랙보드 키)과 출력(성공/실패)을 가져야 합니다.

디버깅 및 시각화

  • AI Debugger (AIDebugger): 언리얼 에디터의 Window -> Developer Tools -> AIDebugger를 사용하여 실행 중인 AI 행동 트리의 현재 상태, 블랙보드 값, 인지 시스템 등을 시각적으로 확인하고 디버깅할 수 있습니다.
  • 콘솔 명령
    • ai.debug [PawnName/ControllerName]: 특정 AI의 디버그 정보 표시.
    • ai.blackboard [PawnName/ControllerName]: AI의 현재 블랙보드 값 표시.
    • showdebug ai: AI 인지 시스템 정보 오버레이.
  • Visual Logger: 10장 2절에서 다룬 Visual Logger를 사용하여 AI의 이동 경로, 목표 변경 등을 시각적으로 기록하고 재생하여 문제를 분석합니다.

성능 고려 사항

  • 불필요한 틱 비활성화: AI 컨트롤러나 컴포넌트의 틱을 최적화합니다. (9장 4절 CPU 최적화 참조)
  • 거리 기반 최적화: 플레이어로부터 멀리 떨어진 AI는 업데이트 빈도를 줄이거나, 행동 트리를 단순화하는 등의 최적화를 적용합니다.
  • EQS (Environment Query System): 복잡한 환경에서 AI가 최적의 위치를 찾을 때 사용됩니다. 유연하고 강력하지만, 오버헤드가 발생할 수 있으므로 필요한 경우에만 사용하고 쿼리를 최적화해야 합니다.

그 외의 AI 관련 기술

  • State Machine (상태 머신): 간단한 AI 행동이나 애니메이션 제어에 효과적입니다. 행동 트리와 결합하여 사용할 수 있습니다.
  • Utility AI (유틸리티 AI): 각 행동에 점수를 부여하여 가장 높은 점수를 얻은 행동을 선택하는 방식입니다. 행동 트리보다 유연하고 상황 적응력이 높을 수 있습니다.
  • Machine Learning (머신 러닝): 최근에는 강화 학습(Reinforcement Learning) 등을 사용하여 AI를 훈련시키고 더욱 복잡하고 예측 불가능한 행동을 만들려는 시도가 활발합니다. 언리얼 엔진은 Reinforcement Learning 플러그인과 외부 ML 라이브러리와의 연동을 지원합니다.

게임 AI는 게임의 몰입도와 재플레이 가치를 높이는 데 결정적인 역할을 합니다. 언리얼 엔진의 AI 컨트롤러, 내비게이션 메시, 그리고 특히 행동 트리와 블랙보드는 복잡한 AI 행동을 시각적으로 설계하고 관리하기 위한 강력한 프레임워크를 제공합니다. 계층적 설계, 블랙보드 활용, 데코레이터 및 서비스의 현명한 사용, 그리고 사용자 정의 작업 구현을 통해 효과적인 AI를 만들 수 있습니다. 또한, 언리얼 에디터의 AI 디버거와 Visual Logger를 적극적으로 활용하여 AI 행동을 분석하고 최적화하는 것이 중요합니다. 이러한 AI 기술들을 숙달한다면, 플레이어에게 잊을 수 없는 경험을 선사하는 게임을 만들 수 있을 것입니다.