
제가 만든 'Global NPC': 다른 레벨에서도 유지되며 플레이어처럼 이동할 수 있는 NPC
요약
Godot 엔진을 사용하여 여러 레벨(Viewport)을 겹쳐 쌓는 방식으로, 레벨 전환 시에도 플레이어를 추격할 수 있는 'Global NPC' 시스템을 구현했습니다. NPC가 특정 레벨에 국한되지 않고 레벨 워프를 통해 자유롭게 이동하며 경로 탐색을 수행하는 기술적 접근을 다룹니다.
핵심 포인트
- 여러 3D Viewport를 중첩하여 레벨 간 충돌 문제를 방지하고 유연한 구조 설계
- NPC가 레벨 워프를 통해 플레이어를 실시간으로 추격하는 Global NPC 시스템 구현
- 최적화를 위해 플레이어가 없는 뷰포트에도 필요한 엔티티만 선택적 로드
- 다중 뷰포트 활성화에 따른 성능 비용 및 레이트레이스 체크 제한 사항 고려
제가 만족스러워하는 결과물을 조금 보여드리려고 합니다. (레딧을 자주 사용하지 않아서 혹시 제가 잘못하고 있는 게 있다면 양해 부탁드립니다!) 저는 제 생애 첫 게임인 'Be Brave Sarah!'를 작업 중이며, 여러 개의 3D Viewport를 사용하여 레벨들을 서로 위에 '쌓는(stack)' 방식을 사용했습니다. 이를 통해 레벨들이 연결되는 방식에 유연성을 가질 수 있고, 한 레벨의 충돌(Collision)이 다른 레벨로 새어 나가는 문제도 걱정할 필요가 없습니다. 여기서 'Upstairs(위층)'와 'Downstairs(아래층)' 레벨은 두 개의 별개 레벨이지만, Upstairs에서 Downstairs 레벨을 보기 위해 레이어(Layer)로 겹쳐져 있습니다. NPC Elizabeth는 이 게임에서 절대 언로드(Unload)되지 않으며, 그녀가 있는 레벨이 눈에 보이지 않더라도 배경에서 해당 레벨이 여전히 로드되어 있기 때문에 이동할 수 있습니다. 저는 이것을 Global_NPC라고 부르는데, 왜냐하면 이들은 하나의 레벨에 국한되지 않고 레벨 사이를 자유롭게 이동할 수 있기 때문입니다. 그녀의 추적 AI는 단순히 플레이어에게 텔레포트하는 것이 아니라 실제로 플레이어를 따라다니며, 플레이어와 마찬가지로 경로 탐색(Pathfind)을 하고 동일한 레벨 워프(Level Warp)를 사용해야 합니다. 1:19 지점에서 Liz가 레벨 워프를 사용하는 것을 볼 수 있습니다. (그녀의 스프라이트(Sprite)가 갑자기 Upstairs 레벨 아래로 레이어링되는 것을 보면 그녀가 Downstairs 레벨에 있다는 것을 알 수 있습니다.) 또한 최적화를 위해 플레이어가 있지 않은 'viewport only' 레벨에 실제로 로드될 엔티티(Entity)를 선택할 수 있도록 만들었습니다. 예를 들어, Global NPC가 문을 여는 소리를 들을 수 있어야 하므로 문(Doors) 같은 것들은 로드되어야 합니다. 제 게임의 경우 전체 게임이 다층 구조의 집에서 진행되기 때문에, 모든 레벨을 한꺼번에 로드하지 않으면서도 플레이어가 어디에 있든 상관없이 특별한 캐릭터들이 각자의 레벨에 로드되어 있어야 했기에 이 기능이 특별히 필요했습니다. 이는 레벨 사이를 넘나들며 플레이어를 추격하고 수색할 수 있는 독특한 최종 적에게 특히 유용합니다. 게임 자체에 대해서 말씀드리자면, Godot에서 RPG 스타일의 엔진을 만들기 위한 구실에 가깝기 때문에 대단한 것을 기대하지는 마세요. 제가 발견한 몇 가지 주의사항/제한 사항은 다음과 같습니다: NPC는 시각적으로 보여야 하는 상황일지라도 다른 레벨에 있는 것들에 대해 레이트레이스(Raytrace) 체크를 할 수 없습니다. 따라서 계단 꼭대기에 서 있으면, 계단 맨 아래에 있는 Global 적은 당신을 보지 못합니다.
이는 적 추격 AI (Enemy chasing AI)가 추격 도중 플레이어가 다른 레벨로 워프 (Warp)할 때 플레이어를 시야에서 놓치게 된다는 사실을 고려해야 하며, 해당 특수한 상황에서도 추격을 계속 유지해야 함을 의미합니다. 레벨 아래로 떨어지면 계속해서 레벨 아래로 추락하게 되는데, 이는 아래에 쌓여 있는 다음 레벨이 환상(Illusion)이기 때문입니다. 이러한 가능성에 대비하여, 플레이어가 허공(Void)으로 떨어지는 경우를 대비해 플레이어를 다음 레벨로 이동시킬 수 있도록 레벨 아래에 레벨 전체를 아우르는 커다란 워프 트리거 (Warp trigger)를 배치했습니다. 이렇게 많은 뷰포트 (Viewport)를 동시에 활성화하는 것은 성능 비용 (Performance cost)이 발생합니다. 어떤 경우에는 특정 상황에서 4개의 레벨이 모두 한꺼번에 로드될 수도 있습니다. 이와 같은 작은 실험용 게임에는 괜찮지만, 여러 내부 공간을 가진 젤다 (Zelda) 규모의 오픈 월드 (Overworld)에서는 끔찍한 일입니다. 레벨 간의 Global_NPC 경로 탐색 (Pathfinding)을 위해서는 레벨 워프 (Level warp)를 설정할 때 연결될 수 있는 모든 가능한 목적지 목록을 설정해야 합니다. 예를 들어, NPC가 레벨 A에서 레벨 B를 거쳐 레벨 C로 가고 싶어 한다면, 레벨 A에서 레벨 B로 가는 워프는 레벨 C와 연결되어 있다는 것을 명시해야 하며, 이와 같은 방식이 계속됩니다. 만약 레벨이 A부터 Z까지 있다면, 각 레벨 사이의 모든 워프는 경로 탐색이 가능한 모든 단 하나의 가능한 레벨까지도 전부 명시해야 합니다. 만약 이 중 하나라도 놓치면, NPC는 단순히 한 레벨에서 다음 레벨로 어떻게 이동해야 하는지 알지 못하게 됩니다. 하지만 이 방식의 멋진 점은, 올바르게 설정만 된다면 NPC가 이론적으로 플레이어와 상관없이 실시간으로 각 레벨을 로드(Loading) 및 언로드(Unloading)하며, 마치 배경에서 플레이어처럼 행동하며 여러 개의 서로 다른 레벨로 구성된 전체 게임 월드를 완전히 스스로 걸어서 이동할 수 있다는 것입니다. submitted by /u/Armystuntman [link] [comments]
AI 자동 생성 콘텐츠
본 콘텐츠는 r/godot (top/week)의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기