A* Pathfinding 프로젝트 시작하기

Pathfinding은 A 지점에서 B 지점까지 최적의 경로를 찾는 것입니다. A* Pathfinding 프로젝트는 이를 수행합니다. 이 튜토리얼에서는 새 장면에 프로젝트를 설정하고, 장애물을 피하면서 간단한 AI를 이동시키는 방법을 배웁니다.

 

이 튜토리얼에서 작성할 AI는 매우 고급스럽지 않으며, 이동하고 경로를 따르는 데 필요한 최소한의 코드만 포함합니다. 더 고급 AI를 원한다면, 이 튜토리얼에서 작성한 스크립트를 확장하거나 패키지에 포함된 AIPath 또는 RichAI 스크립트를 사용하거나 확장할 수 있습니다 (RichAI 컴포넌트의 기본 사용법은 2부를 참조하세요).

 

설치

먼저, A* Pathfinding 프로젝트를 다운로드하세요 (아직 하지 않았다면).

설치 가이드는 여기를 참조하세요: [설치 가이드](링크).

프로젝트는 여기에서 다운로드할 수 있습니다. 기능이 제한된 무료 버전(하지만 여전히 매우 강력함)과 더 많은 기능이 포함된 프로 버전을 구매할 수 있습니다.

원한다면, 다음 섹션을 시작하기 전에 프로젝트의 다양한 예제 장면을 탐색할 수 있습니다. 패키지를 설치하는 방법에 따라 Unity 패키지 관리자에서 예제 장면을 별도로 가져와야 할 수도 있습니다.

 

참조
Example Scenes

 

개요

패키지는 여러 가지 부분으로 나뉩니다. 크게 다음과 같이 그룹화할 수 있습니다:

 

  • 이동 스크립트: 에이전트가 어떻게 이동하고 어디로 이동해야 하는지 알려줍니다 (참조: Movement scripts ).
  • 그래프: 에이전트가 이동할 수 있는 영역을 설명합니다 (참조:  Graph Types ).
  • 임시 장애물: 네비메쉬에 구멍을 내거나 다른 방법으로 업데이트합니다 (참조:  Graph Updates ).
  • 오프-메쉬 링크: 에이전트가 네비메쉬의 분리된 부분 사이를 이동하거나 점프할 수 있게 합니다 (참조: NodeLink2 ).
  • 경로 수정자: 경로를 후처리하여 매끄럽게 만드는 등의 작업을 합니다 (참조: Using Modifiers ).

주로 상호작용할 것은 이동 스크립트와 Seeker 컴포넌트입니다. 둘 다 이동해야 하는 에이전트에 부착되어야 합니다. 이동 스크립트는 에이전트의 이동 방식, 속도, 회전 등을 제어하며, 에이전트의 현재 목적지 및 경로를 다시 계산해야 하는 시점 등을 조절합니다. Seeker 컴포넌트는 이동 스크립트에 의해 제어됩니다. 이동 스크립트는 경로를 계산하도록 Seeker에게 알립니다. 그리고 Seeker는 이동 스크립트로 결과를 반환할 것입니다.

 

AstarPath 컴포넌트는 장면 내의 모든 그래프 데이터를 보유합니다. 이는 싱글톤 패턴을 따르므로 장면 내에는 한 개의 이러한 컴포넌트만 있어야 합니다. AstarPath는 동일한 유형 또는 다른 유형의 하나 이상의 그래프를 포함할 수 있습니다. 각 그래프는 다시 여러 개의 노드를 포함하고 관리합니다 (이 중 일부는 수백만 개가 될 수도 있습니다).

 

패키지에는 AIPath, RichAI, AILerp, FollowerEntity와 같은 여러 이동 스크립트가 포함되어 있습니다. 이 중 하나를 사용하거나 직접 작성할 수 있습니다 (이동 스크립트 작성을 참조하세요). 내장된 이동 스크립트의 비교는 여기에서 찾을 수 있습니다: Movement scripts .

 

비디오 튜토리얼

만약 텍스트 튜토리얼 대신 비디오 튜토리얼을 선호한다면 여기 비디오가 있습니다. 비디오 튜토리얼은 보다 고수준의 접근 방식을 취하며, 사용자 정의하는 대신 내장된 이동 스크립트를 사용하는 방법을 배우게 됩니다. 비디오와 텍스트 튜토리얼이 약간 다른 내용을 다루기 때문에 둘 다 살펴보는 것이 나쁘지 않은 생각입니다.

Unity Cookie의 게이브리얼 윌리엄스가 제공한 훌륭한 튜토리얼도 참고하실 수 있습니다. 이는 타워 디펜스 게임 제작 시리즈의 8부에 해당합니다: [링크](https://www.youtube.com/watch?feature=player_embedded&v=PUJSvd53v4k). 해당 비디오는 텍스트 튜토리얼에서 다룰 대부분의 내용을 다룹니다.

 

새로운 장면

새로운 장면을 만들고 "PathfindingTest"라고 이름 짓습니다. 이제 AI가 걸을 수 있는 무언가를 만들고 피할 것을 만들어 봅시다: 장면에 평면을 추가하고, 장면 원점(0,0,0)에 배치하고 크기를 10,10,10으로 조정합니다.

"Ground"라는 새 레이어를 만들고 장면에 평면을 이 레이어에 배치합니다. 이제 다른 크기의 몇 개의 큐브를 만들고 이를 평면 위에 배치합니다. 이것들은 AI가 피해야 할 장애물이 될 것입니다. 이들을 "Obstacles"라는 새 레이어에 배치합니다.

이제 장면이 이렇게 보일 것입니 다:

 

A* 추가

이제 AI가 서 있을 수 있는 땅과 피해야 할 장애물이 있습니다. 따라서 이제 경로 탐색을 가능하게 하기 위해 장면에 A* Pathfinding 시스템을 추가하겠습니다.

새 GameObject를 만들고 "A*"이라고 이름 짓고, 그에 "AstarPath" 컴포넌트를 추가합니다 (메뉴 바 → Components → Pathfinding → AstarPath).

AstarPath 인스펙터는 여러 부분으로 나뉩니다. 가장 중요한 두 부분은 Graphs 영역과 하단에있는 Scan 버튼입니다. Graphs 영역에는 장면의 모든 그래프가 포함되어 있습니다. 최대 256개까지 보유할 수 있지만 일반적으로 1개 또는 2개가 충분합니다. 단일 그래프가 일반적으로 간단함을 위해 선호됩니다.

Graphs 영역을 클릭하여 열면 추가할 수있는 그래프 목록이 표시됩니다. 이 튜토리얼에서는 그리드 패턴의 노드를 생성하는 GridGraph를 생성합니다.

 

참고:
Graph Types 에서 다양한 그래프 유형에 대해 더 많은 정보를 읽을 수 있습니다.

 

그리드 그래프를 추가한 후에는 해당 레이블을 클릭하여 그래프 설정을 표시합니다.

인스펙터 하단에는 "Scan"이라는 버튼이 있습니다. 이 버튼은 설정 및 세계에 따라 그래프를 계산하는 데 사용됩니다. 설정을 변경한 후에는 변경 사항을 보려면 그래프를 스캔해야 합니다. 이 작업에 대한 편리한 단축키가 있습니다: Cmd+Alt+S(mac) 또는 Ctrl+Alt+S(windows).

게임이 시작될 때 모든 그래프가 기본적으로 스캔됩니다(시작이 캐시된 경우를 제외하고, 이에 대한 자세한 내용은 다른 부분에서 설명합니다).

그리드 그래프는 이름에서 암시하는 대로 width*depth size 의 노드 그리드를 생성합니다. 그리드는 장면의 어디에나 위치시킬 수 있으며 원하는대로 회전시킬 수 있습니다.

노드 크기 변수는 그리드 내의 정사각형/노드의 크기를 결정합니다. 이 튜토리얼에서는 이 값을 1로 설정하여 노드 사이의 간격을 1 유닛으로 유지합니다.

그러나 위치를 변경해야 합니다. 위치 필드 오른쪽의 작은 선택기에서 bottom-left로 변경한 다음 (-50, -0.1, -50)을 입력하십시오. -0.1은 부동 소수점 오류를 피하기 위한 것입니다. 장면의 지면이 Y = 0에 있으므로 그래프의 위치도 Y = 0이어야 합니다. 그렇지 않으면 예를 들어 광선을 캐스트 할 때 부동 소수점 오류가 발생할 수 있습니다 (높이 체크와 같이).

그리드를 장면에 맞추려면 너비와 깊이 변수를 변경해야 합니다. 이 경우에는 둘 다 100으로 설정하십시오. 장면 뷰의 흰색 경계 사각형이 지면을 정확히 둘러싸고 있음을 볼 수 있습니다.

 

Height Testing

노드를 올바른 높이에 배치하기 위해 A* 시스템은 장면에 대해 여러 개의 광선을 발사하여 광선이 어디에서 충돌하는지 확인합니다. 이것이 높이 테스트 설정입니다. [광선 길이] 단위 위에서 아래로 광선이 발사되고, 광선이 충돌하는 곳에 노드가 배치됩니다. 만약 아무 것도 충돌하지 않으면, 만약 "Unwalkable When No Ground" 변수가 토글되어 있으면 걷기 불가능한 지점으로 만들거나, 그렇지 않으면 노드가 그리드에 대해 Y = 0 위치에 배치됩니다.

높이 테스트가 올바른 대상에 충돌하는지 확인하려면 사용되는 마스크를 변경해야 합니다. 현재 모든 것이 포함되어 있지만, 이는 우리의 장애물도 포함될 것입니다. 이것은 우리가 원하지 않습니다. 따라서 마스크를 이전에 만든 "Ground" 레이어만 포함하도록 설정하십시오.

 

Collision Testing

노드가 배치된 후 걷기 가능 여부가 확인됩니다. 이는 구, 캡슐 또는 광선을 사용하여 수행될 수 있습니다. 일반적으로 캡슐이 사용되며, 선호하는 경우 AI 캐릭터와 동일한 지름과 높이를 가지며, 가능한 한 여유 있게 설정됩니다.

우리의 AI는 각각 1과 2의 표준 지름과 높이를 가질 것입니다. 그러나 충돌 테스트를 위한 지름과 높이를 2와 2로 설정하여 여유를 얻을 것입니다.

다음으로 우리가 배치한 장애물을 시스템이 인식하도록 하려면 충돌 테스트를 위한 마스크를 변경해야 합니다. 이번에는 "Obstacles" 레이어만 포함하도록 설정하십시오. 우리의 지면이 장애물로 처리되기를 원하지 않기 때문입니다.

이제 모든 것이 올바르게 설정되었으므로 Scan 버튼을 누를 수 있습니다. 잠시 기다리면 생성된 그리드가 나올 것입니다! (모든 것을 올바르게 수행했다면 그렇습니다. 설정을 아래 이미지와 비교하여 Show Graphs가 true인지 확인하십시오).

 

AI 추가하기

경로 찾기 테스트는 움직이는 요소가 없으면 재미가 없습니다. 그래서 AI를 추가하여 테스트해보겠습니다.

캡슐을 생성하고 Character Controller 컴포넌트를 추가한 후, 평면 위에서 보이는 위치에 배치합니다.

AI에 Seeker 컴포넌트를 추가합니다. 이 스크립트는 다른 스크립트에서 경로 요청을 호출하는 보조 스크립트로, 경로를 부드럽게 하거나 레이캐스트를 사용하여 단순화하는 등의 경로 수정자를 처리할 수도 있습니다.

이제 두 가지 대안이 있습니다. 직접 움직임 스크립트를 작성하거나 내장된 움직임 스크립트를 사용할 수 있습니다. 포함된 스크립트는 튜토리얼에서 작성하는 것보다 훨씬 고급이므로 대부분의 경우 이를 사용하는 것이 좋습니다. 그러나 시스템의 작동 방식을 이해하는 데 도움이 되므로 사용자 정의 움직임 스크립트 작성을 위한 튜토리얼을 따르는 것을 추천합니다.

튜토리얼 하위 페이지를 확인하세요:  Writing a movement script .

포함된 스크립트는 AIPath, RichAI 및 AILerp입니다. AIPath와 AILerp 스크립트는 모든 그래프에서 사용할 수 있으며, RichAI는 주로 내브메쉬 기반 그래프에 사용됩니다. AIPath와 RichAI 스크립트는 경로를 느슨하게 따르지만, AILerp 스크립트는 보간을 사용하여 경로를 매우 정확하게 따라가지만, 실제처럼 보이지는 않을 수 있습니다. 어떤 것을 사용할지는 게임에 따라 다릅니다.

 

참고
포함된 움직임 스크립트에 대한 자세한 정보는 Movement scripts 페이지를 참조하세요. 또한, 포함된 예제 씬에서 이러한 스크립트가 어떻게 사용되는지 확인할 수 있습니다.

 

이 튜토리얼에서는 AI에 AIPath 컴포넌트를 추가할 수 있습니다. 또한, "Target"이라는 이름의 새로운 GameObject를 생성하고 AI가 이동할 위치에 배치합니다. 그런 다음 AI에 AIDestinationSetter 컴포넌트를 추가합니다. 이 컴포넌트는 AIPath 스크립트에 특정 위치로 이동하도록 지시하는 매우 간단한 헬퍼 스크립트입니다. 나중에 이 스크립트를 게임에 맞게 직접 작성한 스크립트로 교체할 가능성이 높습니다. AIDestinationSetter 컴포넌트에는 "target"이라는 단일 필드가 있으며, 여기에 앞서 생성한 "Target" GameObject를 할당합니다.

이제 재생 버튼을 누르면 AI가 목표 지점으로 이동해야 합니다. 움직임 스크립트가 어떻게 작동하고 어떻게 설정하는지에 대한 자세한 내용은 위에 링크된 비디오 튜토리얼에서 설명하고 있습니다. 무언가 제대로 작동하지 않는 경우 해당 비디오를 참조하세요.

 

Smoothing

이제 간단한 그리드 그래프를 설정하고 경로를 계산하는 방법을 배웠습니다. 하지만 경로를 조금 더 매끄럽게 만들 방법이 분명 있을 것입니다.
물론입니다. 경로를 부드럽게 하고 단순화하는 스크립트는 Path Modifiers라고 하며, Seeker와 동일한 GameObject에 추가할 수 있는 스크립트입니다.

가장 간단한 것은 Simple Smooth Modifier로, 이는 메뉴 바 → Components → Pathfinding → Modifiers → Simple Smooth에서 찾을 수 있습니다. 이를 우리의 AI에 추가하세요.

이 수정자는 경로를 여러 번 세분화하여 각 세그먼트가 Max Segment Length 변수보다 작아질 때까지 경로를 세분화한 후, 포인트를 서로 더 가깝게 이동시켜 경로를 부드럽게 할 것입니다. 수정자에는 여러 설정이 있으며, 여기서 모든 것을 설명하지는 않겠습니다. 각 변수에 대한 자세한 내용은 SimpleSmoothModifier 문서를 참조하세요. 이 튜토리얼에서는 Max Segment Length를 1로, Iterations를 5로, Strength를 0.25로 설정할 수 있습니다. 좋은 값을 찾기 위해 실험해 보세요.

이제 다시 재생 버튼을 누르면 경로가 훨씬 부드러워져 우리가 원하던 대로 보일 것입니다.

 

경고
Smoothers는 일반적으로 월드 지오메트리나 그래프를 고려하지 않으므로 너무 많은 평활화를 적용할 경우 경로가 통행 불가능한 지역을 지나갈 수 있습니다. 따라서 평활화를 적용할 때는 주의해야 합니다.

또 다른 유용한 수정자는  FunnelModifier 로, 경로를 크게 단순화할 수 있습니다. 이 수정자는 navmesh/recast 그래프를 사용할 때 거의 항상 사용됩니다.

수정자에 대한 자세한 내용은 Using Modifiers 페이지를 참조하십시오.

 

Logging settings

시스템에서 경로를 계산할 때마다 선택적으로 콘솔에 로깅할 수 있습니다. 이는 시스템이 무엇을 하고 있는지 이해하고 성능 문제를 발견하는 데 큰 도움이 됩니다. 하지만 로깅은 무료가 아니므로 릴리스 빌드에서는 비활성화하는 것이 좋습니다.

로깅 설정은 A* Inspector → Settings → Debug 탭에서 변경할 수 있습니다.

성능을 약간 개선하거나 콘솔 로그를 줄이려면 디버깅을 적게 사용하세요. 경로 찾기 스크립트가 무엇을 하는지에 대한 자세한 정보를 원한다면 디버깅을 많이 사용하세요. InGame 옵션을 사용하면 게임 내 GUI를 사용하여 최신 경로 로그를 표시합니다.

 

결론

이것으로 시작하는 튜토리얼 파트 1이 마무리되었습니다. 이것으로부터 무엇인가를 배워주길 바랍니다. 여기서부터는 나머지 문서를 탐색하거나 프로젝트에 직접 참여할 수 있습니다. 약간 더 나은 AI를 원한다면 프로젝트에 포함된 AIPath 스크립트를 사용할 수 있습니다.

다음 시작 튜토리얼 파트인 navmesh 그래프를 사용하는 부분으로 계속 진행할 수 있습니다: Using navmeshes

또한 사이드바를 살펴보면 이 패키지 사용에 대한 여러 튜토리얼을 찾을 수 있습니다.

행운을 빕니다!

+ Recent posts