2D 내비게이션 설정 방법! (Unity 초보자 튜토리얼)
요약
본 영상은 Unity 엔진에서 2D 경로 탐색(pathfinding) 기능을 구현하는 방법을 초보자에게 안내합니다. 기본적으로 Unity의 내장 내비게이션 기능은 3D에 최적화되어 있어, 2D 환경에서는 'nav mesh plus'와 같은 보조 패키지를 사용하여 2D 전용 네비게이션 컴포넌트를 활성화해야 합니다.
핵심 포인트
- Unity 기본 내비게이션은 3D 기반이므로 2D 사용 시 어려움이 있습니다.
- 2D 경로 탐색을 위해 'nav mesh plus'와 같은 보조 패키지 사용이 필수적입니다.
- 패키지 관리자에서 AI navigation package를 설치하고, 'navigation surface' 컴포넌트를 활용합니다.
안녕하세요, CodeMakie입니다. 자, 여기서 2D 경로 탐색(pathfinding)을 어떻게 설정하는지 배워봅시다. 기본적으로 저는 멋진 2D 게임에 여러 캐릭터들을 가지고 있는데, 제가 어딘가를 클릭하면 그 캐릭터들이 벽을 피하면서 그곳으로 이동할 수 있기를 원합니다. 이는 많은 2D 게임에서 필요로 하는 기능인데, 놀랍게도 Unity에서는 기본적으로 이를 지원하지 않기 때문에 실제로 구현하기가 조금 어렵습니다. 물론 할 수는 있는 방법은 있지만, 매우 까다로운 우회책입니다. 기술적으로 Unity는 기본적으로 내비게이션 기능을 가지고 있지만, 대부분 3D에만 해당합니다. 2D에서 작동하도록 만들 수는 있지만, 아주 이상한 우회책이 됩니다. 다행히도 누군가 이 기능을 가능하게 하는 아주 좋은 패키지를 만들어 주었기 때문에, 우리는 멋진 2D 경로 탐색을 할 수 있게 되었고, 모든 것이 정말 잘 작동하며 사용하기 매우 쉽습니다.
자, 여기 제 시작 장면(starting scene)이 있습니다. 그리고 참고로, 이것은 제가 만든 Game.PracticeLab의 12번째 도전 과제입니다. 이 프로그램은 여러분이 실제로 게임 개발을 배울 수 있도록 하는 것입니다. 모든 것이 직접 실습하는 것에 중점을 두어 여러분이 정말 배우고 있는지 확인합니다. 매주 저는 여러분에게 도전 과제와 그 목표를 제공하고, 여러분은 시작 프로젝트 파일을 다운로드하여 현재 가지고 있는 기술을 사용하여 목표를 해결해야 합니다. 설명란의 링크를 통해 무료로 시도해 보세요. 아무튼, 이 도전 과제의 경우, 목표 중 하나가 2D 내비게이션이었기 때문에, 어떻게 하는지 배워봅시다. 우리는 Unity의 내장 내비게이션 패키지를 사용하고, 그 위에 2D 내비게이션을 활성화하기 위해 보조 패키지를 레이어할 것입니다. 먼저, 패키지 관리자(package manager)를 열어야 합니다. 그리고 여기에서 Unity 레지스트리로 이동하여 AI navigation package를 찾아야 합니다.
바로 여기에 있는 것을 찾아서 설치하세요. 이것을 설치했으니, 가장 먼저 할 일은 'nav mesh'라는 이름의 새로운 빈 게임 오브젝트를 만드는 것입니다. 깔끔하게 정리하기 위해 트랜스폼(transform)을 초기화합시다. 그런 다음 컴포넌트를 추가하고, 여기서 'nav'를 검색하면 여러 개의 nav mesh 네비게이션 컴포넌트가 나옵니다. 지금 당장 사용할 내장 기능은 바로 이 'nav mesh surface'입니다. 하지만 말씀드린 것처럼 Unity의 기본 nav mesh는 정말 3D에서 작동하도록 만들어졌습니다. 2D용이 아닙니다. 기술적으로는 3D 콜라이더(collider)를 사용해서 3D 카메라와 같은 위치에 배치해 볼 수는 있지만, 워크플로우상 아주 좋지는 않습니다. 다행히 누군가 이 정말 멋진 패키지인 'nav mesh plus'를 만들었습니다. 이것은 기본적으로 Unity의 nav mesh가 이미 존재하는 것을 가져와서 2D에 적용하는 역할을 합니다. 정말 좋은 패키지입니다. 사용하기 매우 쉽고 원하는 대로 정확하게 작동합니다. 그러니 이 패키지를 찾아서 zip 파일을 다운로드하거나 클론(clone)하세요. 어떤 방법을 사용하든 상관없습니다. 그런 다음 그 폴더를 프로젝트 에셋(assets)에 압축 해제하세요. 그리고 다시 컴포넌트를 추가해 보면, 이제 훨씬 더 많은 다른 컴포넌트들이 보입니다. 흰색 아이콘이 붙은 것들은 기본적으로 그 패키지에서 온 것입니다. 그래서 말씀드렸듯이, 이 'nav mesh surface' 대신, 이 'navigation surface'를 사용합시다. 생김새는 표준 nav mesh와 거의 같습니다. 만약 그 시스템을 알고 있다면, 이것은 작업하기가 매우 쉽습니다. 기본적으로 같은 것입니다. 이 컴포넌트가 있고, 여기에 다른 것을 추가해야 합니다. 바로 여기 있는 'navigation collect sources 2D'입니다. 그리고 즉시, 이것이 작은 오류를 표시합니다. 다시 말하지만 우리는 2D 게임을 다루고 있기 때문에 XY축으로 회전시켜야 한다고 말하고 있습니다. 보통 2D에서는 XY축에서 작업하기 때문입니다. 비록 일부 게임은 탑다운(top down)일지라도, 일반적으로 2D에서는 XY축에서 작업합니다.
하지만 다행히도, 이것은 단순한 버튼 하나입니다. 자, 이제 끝났습니다. 이 것은 기본적으로 트랜스폼(transform)을 회전시키는 역할을 합니다. 그래서 이제 모든 것이 올바르게 설정되었습니다. 만약 씬 뷰(scene view)에 있다면, 제가 멋진 우주선을 가지고 있습니다. 그리고 지금 '베이크(bake)'를 클릭해도 아무 일도 일어나지 않습니다. 이것이 맞습니다. 자, 새로운 빈 게임 오브젝트(empty game object)를 만들겠습니다. 이름을 'walkable'이라고 지정하겠습니다. 이것이 우리가 걸어 다닐 영역이 될 것입니다. 그리고 여기에서 스프라이트 렌더(sprite render) 컴포넌트를 추가하겠습니다. 그런 다음 완전히 새로운 2D 오브젝트를 만듭니다. 사각형 스프라이트로 만들어 보겠습니다. 참고로, 만약 여기에 있는 메뉴들, 즉 스프라이트, 물리(physics) 같은 것들이 보이지 않는다면, 이것은 여러분이 '2D 패키지'를 설치해야 한다는 의미입니다. 그렇다면 패키지 매니저(package manager)를 열어 이 2D 스프라이트 패키지를 여기에 설치할 수 있습니다. 어쨌든, 여기 사각형이 있습니다. 이것의 이름을 'walkable'로 변경하여 이것을 우리가 걸어 다닐 영역으로 만들겠습니다. 그리고 저는 기본적으로 전체 공간을 차지하도록 할 것입니다. 그리고 여기에서 제가 검은색으로만 설정해 보겠습니다. 그래야 볼 수 있으니까요. 자, 이런 식으로요. 이제 컴포넌트를 추가하겠습니다. 그리고 다시 '내비게이션(navigation)'을 검색해 보겠습니다. 이번에는 이 '네비게이션 모디파이어(navigation modifier)'를 원합니다. 바로 이것입니다. 그리고 이렇게, 네비메시(navmesh)로 돌아가서 '베이크(bake)'를 클릭합니다. 자, 이제 보시다시피 작은 파란색 영역이 생겼습니다. 이것이 기본적으로 파란색의 걸어 다닐 수 있는 네비메시입니다. 좋습니다, 멋지네요. 이렇게 해서 이미 작동하고 있습니다. 이제 이 'walkable' 게임 오브젝트 위에서 우리는 이 게임 오브젝트를 비활성화하거나, 아니면 스프라이트 렌더(sprite render)만 비활성화하여 보이지 않게 할 수 있습니다. 어느 쪽이든 작동합니다. 만약 이것을 가지고 있다면, 잠시 후에 제가 실제로 이러한 벽들을 어떻게 정의할 수 있는지 보여드리겠습니다. 하지만 그 전에, 이 네비메시를 사용해 보는 것을 먼저 시도해 봅시다. 어딘가로 걷게 해봅시다. 좋습니다. 그래서 이 데모에는 심볼 캐릭터(symbol character)가 있습니다. 이 캐릭터를 걸어 다닐 수 있는 네비메시로 만들려면, 컴포넌트를 추가하기만 하면 됩니다. 자, 무언가를 추가해 보겠습니다. '내비게이션'을 검색하거나, 아니면 그냥 '네비(nav)'라고 하겠습니다.
그리고 여기 있는 'NavMesh Agent'를 가져오고 싶습니다. 이 에이전트가 실제 NavMesh 위에서 이 오브젝트를 움직이는 역할을 할 것입니다. 기본 설정들이 이렇게 되어 있습니다. 이것들을 조금 가지고 놀아 볼 수 있습니다. 예를 들어, 2D에서는 단위(unit)가 실제로 상당히 작습니다. 그래서 속도(speed)는 0.75 정도에 두겠습니다. 3.5는 아마 너무 빠를 겁니다. 자, 이 컴포넌트가 생겼습니다. 우리는 기본적으로 이 컴포넌트에 어디로 이동해야 할지 알려주기만 하면 됩니다. 여기서는 스크립트를 만들겠습니다. 'NavMesh Movement'라는 이름의 새로운 모델 동작(model behavior)을 만듭니다. 그리고 여기에는 아주 간단하게 그것을 정확히 같은 오브젝트에 붙입니다. 자, 'private void Awake'로 가보겠습니다. 그리고 Awake에서 네임스페이스 UnityEngine.AI 안에 있는 private NavMeshAgent를 정의하겠습니다. NavMeshAgent를 가져옵니다. 그리고 Awake에서 단순히 NavMeshAgent = GetComponent<NavMeshAgent>()를 사용합니다. 이렇게 해서 그것을 얻어냅니다. 그리고 그것에게 어딘가로 이동하라고 알려주려면, 간단한 'private void Update'를 사용합시다. 그리고 Update에서는 NavMeshAgent에 들어가서 이 목적지(destination)를 설정합니다. 무언가로 설정합니다. 자, Expo에서 디버그 트랜스폼을 만듭니다. 직렬화된 필드(serialized field)인 private Transform targetPositionTransform을 만듭니다. 이것이 하나 있고, 여기에 가서 그 위치의 'position'으로 갑니다. 네, 맞습니다. 에이전트에게 특정 위치로 가라고 알려주는 것이 이렇게 간단합니다. 목적지(destination)만 업데이트하면 결국 그곳에 도착할 것입니다. 자, 여기 캐릭터에는 이 컴포넌트인 NavMesh Movement를 붙이고요. 그리고 목표 위치(target position)의 경우, 새로운 빈 게임 오브젝트를 만들겠습니다. 'Target Position'이라고 이름 지어보죠. 그리고 여기에 아무데나 배치해 보겠습니다. 이제 본질적으로 유닛은 저쪽을 향해 곧장 이동해야 합니다. 자, 우리의 목표 위치를 할당하겠습니다. 좋습니다. 자, 테스트해보겠습니다. 바로 보시다시피 실제로 투명합니다. 이것은 버그가 아니라 의도된 동작입니다.
이것은 제가 말씀드렸던 것과 관련이 있습니다. Unity가 기본적으로 2D 내비메쉬(navmesh)를 제대로 지원하지 않기 때문입니다. 그래서 이것을 아주 쉽게 수정할 수 있습니다. 여기에서, 만약 이 최대화 버튼을 누르지 않고 실제로 보면 볼 수 있습니다. 네, 저기요. 캐릭터가 실제로 거기에 있습니다. 하지만 이것을 3D 뷰에 넣으면 문제가 보입니다. 저기요. 스프라이트가 바로 거기에 있습니다. Y축이 아닌 Z축을 향하고 있습니다. 이 문제는 다시 말해, 내비메쉬는 정말로 3D에서 작동하도록 설계되었고, Z축을 기준으로 작동해야 하며, 실제로 2D에서 작동하도록 설계된 것이 아니기 때문입니다. 하지만 캐릭터는 저쪽에 있습니다. 만약 제가 실제로 목표 위치를 이동시켜 본다면, 움직여 보면 저기요, 캐릭터가 보입니다. 네, 저기요. 캐릭터가 확실히 움직이고 있습니다. 그래서 네, 그것은 작동합니다. 단지 올바른 방향을 바라보지 못하고 있을 뿐입니다. 따라서 다시 말해, 다행스럽게도 우리가 멋진 Learn 패키지를 추가했기 때문에 작업하기가 매우 쉽습니다. 여기에서 컴포넌트를 추가해 보겠습니다. 내비게이션(navigation)을 다시 검색합니다. 그리고 지금 우리가 원하는 것은 바로 이것, 'Agent Override 2D'입니다. 이것은 기본적으로 XY축을 바라보도록 하여 Z축을 향하게 만듭니다. 이제 다시 테스트해보면, 네, 저기요, 이제 캐릭터를 실제로 볼 수 있습니다. 여기 있습니다, 있어야 할 곳으로 완벽하게 움직이고 있습니다. 지금 빠진 유일한 것은 회전(rotation)이 아니라는 점입니다. 그래서 제가 아래쪽에 놓아보겠습니다. 네, 저기요. 그것은 기본적으로 항상 같은 방향으로만 움직입니다. 그게 전부입니다. 그러니 이것을 수정해 보겠습니다. 이 부분에 대해서는 다시 한번 매우 유용하고 멋진 컴포넌트를 추가할 수 있습니다. 컴포넌트를 추가해 보겠습니다. 그리고 이 두 개 중 'Rotate 2D'가 있습니다. 그리고 이 것이 본질적으로 그것이 100% 정확하게 회전하도록 만듭니다. 그래서 아주 빠르고 거의 완벽한 움직임을 합니다. 하지만 아마도 부드럽게 움직이는 것을 원할 가능성이 높습니다. 따라서 이 컴포넌트 대신에 다른 것, 'Rotate Smooth 2D'를 추가할 수 있습니다. 그리고 이것에는 일종의 각속도(angular speed)를 설정할 수 있는데, 예를 들어 300 같은 것입니다. 이제 테스트해보면, 네, 저기요. 그리고 제가 어딘가로 움직이면, 네, 저기요, 이제 조금 더 부드럽게 회전합니다.
좋습니다, 멋지네요. 캐릭터가 경로 탐색(pathfinding)을 따라 걸어 다니고 있습니다. 네트 메쉬(net mesh)를 가로질러 걷고 있어요. 정말 좋습니다. 회전도 하고요. 올바른 방향을 향하고 있습니다. 모든 것이 완벽합니다. 자, 이제 실제 경로 탐색을 테스트할 수 있도록 벽들을 좀 추가해 보겠습니다. 이를 위해 여기 걸어 다닐 수 있는 메쉬(walkable mesh)가 있습니다. 이것을 복제해서 비걸어 다니는 영역(non-walkable)으로 만들 수 있습니다. 그리고 제가 이것을 가져와서, 예를 들어 여기 중앙쯤에 놓아보겠습니다. 그리고 저쪽 내비게이션 수정자(navigation modifier)에서 이 영역을 덮어쓸 수 있습니다. 여기서 '이것은 걸어 다닐 수 있는 영역인가, 아니면 비걸어 다니는 영역인가'를 정의할 수 있습니다. 지금은 이것을 비걸어 다니는 영역으로 만들어 보겠습니다. 여기 이 영역이 일종의 벽이 되도록 하겠습니다. 그리고 이렇게만 하면 됩니다. 다시 내비 메쉬(nav mesh)로 돌아가서 베이크(bake)합니다. 자, 됐습니다. 이제 그 영역은 비걸어 다니는 것으로 표시되었습니다. 따라서 만약 이 두 개를 모두 숨긴다고 가정해 봅시다. 그리고 플레이 버튼을 눌러 테스트하면, 어떻게 돌아가야 하는지, 파란색 부분만 지나고 이 부분들은 피하는지 볼 수 있을 것입니다. 네, 캐릭터가 주변을 걸어 다닙니다. 네, 저기서 넘어가지 않습니다. 제가 이것을 놓으면, 여기에도 놓을 수 있습니다. 자, 보세요. 기본적으로 모든 벽 주변을 돌아다니며 걷습니다. 아주 좋고 완벽합니다. 좋습니다, 멋지네요. 이런 식으로요. 이제 이 오브젝트들을 여러 개 복제해서 모든 벽에 완벽하게 배치할 수 있습니다. 이것은 한 가지 방법입니다. 하지만 실제로 더 쉬운 방법이 또 있습니다. 내비 메쉬는 사실 두 가지 별개의 방식으로 작동합니다. 다른 시각적 요소나 물리적인 경계(physical letters)와 함께 사용할 수 있습니다. 여기 내비게이션 서피스(navigation surface)에서 볼 수 있습니다. 첫째, 레이어(layers)를 포함할 수 있습니다. 원한다면 모든 것을 별도의 '내비게이션' 레이어에 배치할 수 있습니다. 둘째, 지오메트리(geometry)를 사용합니다. 렌더 메쉬(render meshes)를 사용할 수 있는데, 이것은 기본적으로 보이는 것, 즉 우리가 지금 사용하고 있는 것입니다.
따라서 스프라이트가 렌더링되는 모든 것이 이 nav mesh modifier 컴포넌트를 가지고 있다면, 그것을 이동 가능(walkable)하거나 이동 불가능(unwalkable)하게 만듭니다. 또는 이 물리적인 문자들을 사용할 수도 있습니다. 저는 개인적으로 이 방법을 선호합니다. 그리고 이것은, 제가 'bake'을 클릭하면 아무것도 베이크되지 않습니다. 왜냐하면 콜라이더가 없기 때문입니다. 하지만 제가 walkable mesh 위로 가서, 그리고 이것에 대해 전체를 이동 가능하게 만들고 싶습니다. 그래서 저는 2D에 박스(box)와 라이트(light)를 추가할 것입니다. 다시 한번 기억하세요. 3D가 아니라 2D에서 작업하는 것입니다. 그리고 이 nav mesh처럼, 제가 베이크하면, 저기 보이듯이 그것으로 돌아옵니다. 이제 이동 불가능한 것(non-walkable)에 대해 말하자면, 이것도 마찬가지입니다. 만약 제가 2D에 박스와 라이트를 추가한다면, 저는 결국 ~
AI 자동 생성 콘텐츠
본 콘텐츠는 YouTube Code Monkey (Unity C#)의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기