The Low-Tech AI of Elden Ring

개요

엘든 링의 NPC AI는 Havok Script 기반의 로우테크(low-tech) 시스템을 사용하여 복잡하고 예측 불가능한 행동을 구현하며, Pushdown Automaton(PDA) 구조와 이벤트 기반 인터럽트 시스템을 통해 동적인 상호작용을 가능하게 합니다.

주요 내용

* AI 구조: Pushdown Automaton (PDA)
* AI의 의사 결정은 "Goal"이라는 상태의 스택(stack)으로 관리되며, 현재 실행 중인 Goal은 스택의 맨 위에 위치합니다.
* 각 프레임마다 스택의 최상단 Goal이 업데이트되고, 필요에 따라 하위 Goal(Sub-Goal)을 스택에 푸시(push)할 수 있습니다.
* Goal의 업데이트 결과(Continue, Success, Failure)에 따라 스택에서 Goal이 팝(pop)되거나 스택이 해제(unwind)될 수 있습니다.
* "activate" 콜백 함수는 Goal이 처음 업데이트될 때 호출되며, Actor의 컨텍스트와 무작위성을 사용하여 다음 행동을 결정하고 새로운 Goal을 푸시합니다.
* 행동 결정은 주로 가중치 기반 무작위 선택을 통해 이루어지며, 거리를 포함한 다양한 요소를 고려하여 가중치가 동적으로 조정됩니다.
* 인터럽트 시스템
* "interrupt" 콜백 함수는 외부 이벤트(예: 플레이어의 행동, 상태 변화)에 즉각적으로 반응하도록 설계되었습니다.
* 인터럽트는 현재 Goal 및 상위 Goal로 재귀적으로 전달되며, 인터럽트를 처리한 Goal이 true를 반환하면 처리가 중단됩니다.
* 이를 통해 특정 조건(예: 플레이어가 불에 휩싸임)에서 즉시 공격 패턴으로 전환하거나, 플레이어의 아이템 사용에 반응하는 등 예측 불가능한 행동을 구현합니다.
* 동적으로 구성된 공간 감지 영역(spatial watch regions)을 통해 플레이어의 위치 변화에 따라 인터럽트를 트리거하여 AI 행동을 즉시 조정할 수 있습니다.
* 기타 AI 메커니즘
* Timeouts: 각 Goal에는 생명력(lifetime) 값이 있어, 특정 상태에 갇히는 것을 방지하는 버그 완화 메커니즘으로 사용됩니다.
* Actor Data Access: Actor에는 부동 소수점(float) 배열이 있어 Goal들이 데이터를 임의로 설정하고 읽는 데 사용됩니다. Initialise 콜백 함수는 Actor가 새로운 Top Level Goal을 할당받을 때 이 데이터를 재설정하는 데 사용됩니다.
* 애니메이션 기반 행동: AI의 실제 행동은 주로 애니메이션을 통해 수행되며, 애니메이션 이벤트는 히트박스 정보, 특수 효과 트리거, 투사체 생성 등 다양한 요소를 포함합니다.
* Havok 미들웨어 활용: AI 스크립팅(Havok Script), 애니메이션(Havok Animation Studio), 물리(Havok Physics), 경로 탐색(Havok AI) 등 게임의 다양한 핵심 기술 요소에 Havok 미들웨어가 사용되었습니다.
* 디자인 및 구현 유연성
* AI 스크립트는 "logic" 스크립트와 "battle" 스크립트로 분리되어 재사용성과 맞춤 설정을 용이하게 합니다.
* 레벨 디자이너는 레벨 편집기에서 Actor의 Top Level Goal을 직접 설정하여, 일반적인 전투 외의 수동적인 행동 패턴을 가진 NPC를 배치할 수 있습니다.
* 핵심적인 AI 기능(Attack, MoveToSomewhere 등)은 C++로 구현되어 스크립트의 유연성과 성능 사이의 균형을 맞추고 있습니다.
* Pushdown Automaton은 Behavior Trees나 복잡한 플래너(Planner) 기반 시스템에 비해 실행 속도가 빠르며, 동적인 상태 전환으로 인해 상태 폭발을 피하면서도 명령형(imperative) 코드로 AI 기능을 구성하기 용이합니다.

시사점

엘든 링의 AI 시스템은 복잡한 AI 알고리즘 대신, PDA 구조와 이벤트 기반 인터럽트를 활용하여 게임 디자이너와 애니메이터에게 높은 제어권을 부여하고, 이를 통해 효율적이면서도 플레이어에게는 예측 불가능하고 도전적인 경험을 제공하는 성공적인 사례를 보여줍니다.

원문 읽기 →
원문을 불러오는 중...

댓글

GitHub Discussions