
유닛 여러 개가 같은 목표로 이동하면 다 겹쳐버린다. 길찾기만으로는 부족하고 서로 밀어내는 처리가 필요하다. Godot의 NavigationAgent2D에는 Avoidance 기능이 내장되어 있는데, 처음엔 그냥 켜면 되는 줄 알았다.
그냥 켜면 안 된다
avoidance_enabled = true로 설정하면 끝인 줄 알았는데, 실제로 켰더니 유닛들이 이상하게 진동하거나 벽에 끼는 문제가 생겼다. 이유를 찾아보니 몇 가지를 같이 설정해야 했다.
먼저 유닛마다 CollisionShape2D 대신 원형 콜리전을 써야 Avoidance 계산이 제대로 된다. Avoidance는 에이전트를 원형으로 취급하기 때문에 사각형 콜리전과 계산이 맞지 않는다. 반지름 값도 실제 유닛 크기에 맞게 조정해야 했다.
velocity를 직접 써야 한다
NavigationAgent2D에서 avoidance를 쓰면 velocity_computed 시그널이 생긴다. 이걸 연결해서 계산된 velocity를 받아 써야 한다. 내가 계산한 방향으로 바로 이동시키면 avoidance가 무시된다.
흐름은 이렇다. 목표 지점 방향으로 velocity를 계산하고 NavigationAgent2D.set_velocity()로 넘긴다. 그러면 avoidance 계산이 돌아가고 velocity_computed 시그널로 보정된 velocity가 돌아온다. 그걸 CharacterBody2D.velocity에 넣고 move_and_slide()를 호출한다.
motion_mode 설정도 중요하다
CharacterBody2D의 motion_mode를 FLOATING으로 바꿔야 했다. 기본값인 GROUNDED 모드에서는 중력 방향 처리가 개입해서 2D 탑다운 게임에서 유닛이 이상하게 움직인다. FLOATING으로 바꾸고 나서야 안정적으로 됐다.
그리고 게임 시작 시점에 NavigationAgent2D의 초기 target_position을 유닛 자신의 위치로 설정해줘야 한다. 안 하면 첫 프레임에 (0, 0)으로 이동하려는 경로가 잡혀서 유닛이 맵 구석으로 튀어가는 버그가 생긴다.
정리하자면
Godot Avoidance는 제대로 설정하면 꽤 잘 동작한다. 핵심은 세 가지다. 원형 콜리전 쓰기, velocity_computed 시그널 연결하기, motion_mode를 FLOATING으로 바꾸기. 이 세 가지만 챙겨도 유닛들이 서로 겹치지 않고 자연스럽게 이동한다.








