1. 개요
언리얼엔진으로 수중환경에서 돌아다니는 AI를 구현해야 하는 상황이었다. 언리얼엔진은 2D NavMesh만 지원하는데 3D NavMesh를 대체 어떻게 구현해야 하는지 자료조사를 해봤지만, 역시나 도움이 될만한 정보는 없었다. Fab에서 판매하는 **Flying Navigation System** 플러그인을 활용하면 3D NavMesh 환경을 구현할 수 있었지만, 플러그인 내에서 제공하는 MoveTo는 형편 없었다. 장애물 인식을 하긴 하는데 정밀하지 못했고, 벽에 끼어 못 움직이는 상황이 태반이었다.
2. 문제 상황
우선 수중생물을 구현하고자 **Death In The Water 2** 스팀 게임을 참고했다.
(1) Character Movement 감속 / 가속
상어의 움직임을 분석해보면 우선 감속과 가속을 활용하여 이동하는 것을 볼 수 있다. 일반적으로 Idle 상태에서는 느린 속도로 이동을 하다가 공격을 받거나 플레이어에게 공격을 하러 다가올 때는 보다 빠른 속도로 이동한다. 이때 감속과 가속이 활용된다.
언리얼엔진내의 Character Movement Component 에서 감속과 가속 옵션을 제공해주지만, 수중생물의 느낌보다는 사람이 빠르게 달리다가 멈출 때 혹은 회전할 때 감속하는 느낌이었다. 이 느낌이 부자연스럽게 다가오긴 했지만, 본질적인 문제는 또 있었다. 플레이어를 빠르게 추격하며 다가올 때 플레이어가 방향을 틀어버리면 AI 또한 방향을 틀며 이동을 하는데 이때 감속이 발생한다.
이때 발생한 감속으로인해 AI는 의도치 않은 움직임을 출력하게 되고, 이때 벽 혹은 NavMesh의 경계면에 낑겨버리는 현상이 발생한다. 물론 이런 문제 상황이 발생했을 때 가장 가까운 NavMesh 지점으로 SetActorLocation을 하면 쉽게 해결이 되겠지만, 플레이어 입장에서는 몰입도의 측면에서 다소 달갑지 않은 상황일 것이다.
(2) Execute Task / TickTask
언리얼엔진으로 AI좀 구현해본 사람들은 알 것이다. BTTask 내부적으로 **Execute Task**와 **TickTask**가 구현이 되어있는데, 간단하게 보면 Execute Task는 1회성 호출이고 TickTask는 Tick마다 호출되는 함수라고 생각하면 된다.
Flying Navigation System 플러그인에서 제공하는 MoveTo를 Execute Task에서 호출하는가 TickTask에서 호출하는가에 따라서도 큰 차이가 발생한다. Execute Task는 1회성 호출이므로 경로를 한 번 지정하고나면 그 경로가 잘못된 경로인지 인식을 하지 못 했다.
플레이어가 NavMesh 바깥으로 이동하는 상황이다. 하지만 AI는 플레이어가 바깥으로 나갔음에도 아직 플레이어를 쫓아갈 수 있을 것이라 희망을 품으며 벽에 붙어 움직이지 않는 모습을 볼 수 있다. 물론 최대의 Chasing 시간을 둠으로써 다른 이동경로로 교정하긴 하지만, 역시나 부자연스럽다.
그렇다면 TickTask를 사용하면 될 것 같지만, TickTask도 나름대로 문제가 있었다. Tick마다 MoveTo를 호출하면 매 틱마다 경로를 생성하기 때문에 플레이어가 NavMesh 바깥으로 이동하는 순간을 포착할 수 있다. 하지만 매 Tick마다 경로를 생성하면 해당 경로가 올바른 경로인지 제대로 검사하지 못 한다. 때문에 다음과 같은 상황이 발생한다.
매 Tick마다 경로를 생성하기때문에 움직임은 굉장히 자연스럽지만, 벽에 끼어버렸다.
3. 결론
Flying Navigation System에서 제공해주는 MoveTo는 장애물이 여럿 배치되어 있는 상황에서는 유용하게 활용할 수 없다. 하지만 3D 환경을 인식하여 AI의 이동반경을 생성해주는 기능은 쓸만하다.
결론적으로 나는 Flying Navigation의 MoveTo를 대체할만한 기능을 자체적으로 구현하기로 했다.
'언리얼 엔진 > 트러블슈팅' 카테고리의 다른 글
| [언리얼엔진] enum타입 TArray (1) | 2025.08.01 |
|---|---|
| [언리얼엔진] C++ 파일 경로 문제 (0) | 2025.06.18 |
| [언리얼엔진] Behavior Tree 인스턴스 (1) | 2025.05.28 |
| [언리얼엔진] ApplyPointDamage (0) | 2025.05.20 |
| [언리얼엔진] Simulate Physics + Physics Asset (0) | 2025.05.20 |