개요
조종행동을 이용해서 자연스럽게 동작하는 AI를 만들자.
사이드 프로젝트인 EternalSmash를 제작하면서 적을향해 움직이는 AI가 필요했다.
이동하다가 이동 경로에 장애물이 생기면 회피를 해야하는데, 자연스럽게 회피하는 것을 구현하기가 어려웠다.
이 부분을 조종행동으로 해결할 수 있겠다는 생각이 들어서 직접 구현하게 되었다.
조종행동
조종행동은 어떠한 목표를 이루기 위해 주변 환경을 감지하여 상황에 맞는 행동들을 수행하여 목표를 이루는 자동적 에이전트를 만드는 방법이다.
적을 따라가거나, 피하거나, 목표에 도착하는 등 여러 행동들을 상황에 맞게 조합해야한다.
목표를 향해 이동하다가 적을 마주하면 회피하면서 주변 무리들로부터 너무 멀어지지 않게끔 조절해야한다.
위의 내용을 구현하기 위해선 주변 환경을 감지하여 자신이 어떤 행동을 해야하는지 판단할 수 있어야 한다.
또, 앞으로 나아가려는 힘과 적으로부터 도망치려는 힘을 잘 배분해야 적절한 행동을 취할 수 있다.
이런 조종행동을 구현하기 위해선, 크게 세 가지 레이어로 구분하여 구현해야 한다.
액션선택
목표를 선택하고 어떤 행동을 조합해야 하는지 결정한다.
조종
선택한 목표와 조합된 행동을 통해 적절한 궤적을 계산한다.
이동력
에이전트가 어떤 방식으로 이동할지를 표현한다.
이런 내용들을 지금 필요한 상황에 맞게 조금씩 변형해서 구현했다.
구현
위에서 언급한 세 가지 레이어중 첫 번째 레이어인 액션선택은 FSM을 통해 구현했다.
어느 위치로 이동해야하거나, 대기해야 하는등 목표를 행동 단위로 구분하고, 어떤 행동들이 조합 되어야 하는지는 그 행동 안에 정의하는 방식으로 구현했다.
두 번째 레이어인 조종은, Agent라는 클래스를 만들고 행동을 정의했다.
이동, 회피 등의 행동을 하기 위해선, 상대 Agent 인스턴스가 필요하다. 상대 Agent에 가해지고 있는 힘이나, 나아가고자 하는 방향을 조합하여 어떻게 움직여야할지 계산했다.
세 번째 레이어인 이동력은 구현하지 않았다.
당장은 모든 에이전트가 동일한 방식으로 이동할 것이기 때문에 이 부분은 제외했다.
Agent
Agent 클래스는 조종행동의 행동들이 정의되어 있다.
어떤 행동을 수행하기 위한 조종값을 만들고, 만들어진 여러 조종값을 가중치에 맞게 가공하여 실제 동작할 조종값을 만들어주는 클래스이다. 이 클래스에는 Velocity, Heading, FSM, AgentInfo, BlackBoard가 정의되어 있다.
Velocity
현재 가해지고 있는 힘이다. Vector2로 표현되어있다.
여러 행동들의 값을 모두 더한다음, 가중치에 맞게 잘라낸 값이 저장되어있다. 이 값에 Time.deltaTime을 곱한만큼 이동한다.
Heading
현재 이동중인 방향의 정규벡터이다. Vector2로 표현되어있다. Velocity의 값이 정해지고 나면 그 값을 정규화 하여 저장한다.
FSM
액션선택의 역할을 하는 FSM이다. 할당할때 Agent의 정보가 필요하기 때문에 Agent가 가지고 있으며, Agent가 생성될때 FSM도 함께 생성한다.
AgentInfo
Agent의 이동속도, 반지름 크기 등 Agent의 기본 정보들이 들어가있는 클래스이다.
BlackBoard
외부 데이터를 전달해주는 클래스이다.
근처에 있는 Agent의 정보를 가져오는 등 외부 데이터에 맞게 대응해야하는 경우에 사용된다.
상태와 행동
Agent가 동작할때 필요한 두 가지 요소가 있는데, 상태와 행동이다.
상태
상태는 현재 해야 하는 최종 목표이다.
예시로는 대기하기, 목적지로 이동하기, 목표를 공격하기, 목표를 추격하기 등이 있다.
행동
행동은 어떤 상태를 이루기 위해 필요한 동작들이다.
대기하기 상태에선, 가만히 있다가 아군이 지나가려고 하면 스윽 움직여서 비켜주어야한다.
이동하기 상태에선, 목표를 향해 이동하다가도 아군이 있으면 반대방향으로 틀어서 비켜주어야 하고, 장애물이 있다면 급격하게 방향을 틀어야 한다.
즉 한가지 상태를 유지하기 위해서 여러가지 행동들의 조합이 필요하다. 이렇게 조합해야 하는 여러가지 요소들 하나하나가 행동이다.
동작
FSM에서 상태가 결정되면 Agent에게 어떤 행동을 하라는 요청을 한다.
Agent에선 여러가지 행동들을 조합해서 나온 결과값을 통해 움직이는데, 행동의 우선순위가 더 높다면 가중치를 높게 설정해서 그 행동을 우선적으로 수행하도록 한다.
마치며
이번엔 간단하게 조종행동을 어떤 구조로 설계했고, 구현했는지를 작성했다. 다음엔 실제로 어떻게 동작하는지는 작성해보겠다.
'게임 프로그래밍 > 게임 AI' 카테고리의 다른 글
[게임 AI] 조종행동(SteeringBehavior) 3 (0) | 2025.02.01 |
---|---|
[게임 AI] 조종행동(SteeringBehavior) 2 (0) | 2025.02.01 |
[게임 AI] A* 알고리즘 vs JPS 알고리즘 성능 비교 (0) | 2024.08.01 |
[게임 AI] JPS(Jump Point Search) 알고리즘 (0) | 2024.07.23 |
[게임 AI] A* (에이스타) 알고리즘 (0) | 2024.07.17 |