A* Pathfinding Project 사용법 - 1. Unity 내에서 사용 (스압주의)
블랙 프라이데이로 할인해서 산 에셋이다.
https://assetstore.unity.com/packages/tools/ai/a-pathfinding-project-pro-87744
A* Pathfinding Project Pro | AI | Unity Asset Store
Get the A* Pathfinding Project Pro package from Aron Granberg and speed up your game development process. Find this & other AI options on the Unity Asset Store.
assetstore.unity.com
게임에서 길찾기 기능은 필수적인 요소인데 A* 알고리즘을 이용하여 최적화된 길을 찾아주는 에셋이다.
1. 지형 만들기
사용하기 위해 먼저 지형을 만든다.
빨간색 Cube는 "Wall" 이라는 Layer로, 흰색 Cube는 "Obstacle"이라는 Layer로 지정하였다.
베이지색 Plane은 "Ground"라는 Layer로 지정하였다.
2. "Pathfinder" Component 적용한 GameObject 만들기
1) Component 추가
그 다음 현재 지형 중 어디가 갈 수 있는 길인지 알아야 하는데, 이 역할을 pathfinder가 한다.
Create Empty로 GameObject를 만들고 "pathfinder" component를 추가한다.
해당 GameObject의 이름은 A* 알고리즘을 적용하기 위한 발판으로 사용되니, "A*"라고 짓도록 하자.
2) Graph 생성
① Grid Graph 생성과 크기 조절
길 인식을 위한 여러 종류의 Graph가 있다.
한 Pathfinder에 대해서 최대 256개의 Graph를 추가할 수 있지만, 1~2개면 충분하다.
일단 사용법을 익히기 위해 Grid Graph를 사용하고, 나머지 Graph는 해당 에셋을 좀 사용하다가 포스팅할 것이다.
(할 일 추가)
무튼 Grid Graph를 선택시, Scene에 아래와 같은 Grid 모양의 판이 나오는 것을 확인할 수 있는데, 이는 길을 탐색할 범위를 나타낸다.
크기는 아까 만든 'Grid Graph' 선택시 나타나는 세부사항의 Width와 Depth를 통해 조절할 수 있으며,
굳이 저것으로 조절하지 않더라도 Scale tool로도 할 수 있다.
또한 크기조절뿐만 아니더라도, Center를 지정할 수 있고, Rotation도 가능하다.
Node Size는 Grid의 정사각형 크기를 의미한다.
아마 맵 Tile의 최소 크기만큼 지정하면 되지 않을까 싶다.
이 포스트에선 1로 지정하고 사용한다.
그리고 대충 길찾기를 실행할 범위까지 늘려준 다음, 해당 Graph의 Center값 중 Y값을 -0.1로 해주자.
(해당 Scene의 Ground Layer는 Y = 0부터 시작한다. 만약 Graph의 Y값도 0이면 나중에 높이 확인등을 할 때 '부동 소수점 오류'가 발생할 수 있어, 반드시 Ground의 Y값보단 낮게 설정해줘야 한다.)
② Scan 해보기
Scan을 실행하면(숏컷으로 Windows는 Ctrl+Alt+S, Mac은 Cmd+Alt+S로 실행할 수 있음)
아래와 같이 파란색 영역이 나온다.
해당 영역은 '갈 수 있는 영역'을 의미한다.
혹여나 색이 맘에 안든다면, [Graphs] 아래에 있는 [Settings]에서 변경할 수 있다.
③ Height Testing과 Collision Testing 설정
먼저 살펴볼 것은 Height Testing이다.
이는 Ray length, Mask, Thick Raycast, Unwalkable when no ground로 구성돼있다.
- Ray length : 갈 수 있는 높이 지정
- Mask : 갈 수 있는 Layer Mask 지정
- Thick Raycast : Scene으로 ray casting하는 ray의 굵기
- Unwalkable when no ground : Raycasting한 것이 Mask로 지정한 Layer가 아닐 시 갈 수 있는지 없는지 결정
Height Testing을 위해 Scene에 ray를 발사하여 측정하는 듯 하다.
아마 이를 그림판을 이용해 나타낸다면, 아래와 같은 형태가 될 것이다.(뇌피셜)
이런식으로 raycasting을 하여, Mask로 지정한 Layer가 나올 시(Ground등) Walkable로 만들고,
만약 Wall 또한 Mask로 지정시, diff값(※ Wall의 Y값 - Graph의 Y값)을 계산하여
Ray length보다 낮거나 같다면, Wall의 윗부분도 갈 수 있도록 계산하는 방식인것 같다.
(물론 Wall을 Mask로 지정하지 않으면 그냥 무시하고 못가는 지역으로 계산할 것임)
이때 Ground를 벗어날 시, 어떻게 처리할까에 대해선 'Unwalkable when no ground'가 담당하며,
체크하면 갈 수 있고, 체크를 안하면 갈 수 없도록 한다.(※ 기본적으로 체크 돼있다.)
Thick Raycast는 언제 어떻게 사용하는지 잘 모르겠다..
무튼 Mask를 Ground로 지정해서, Ground Layer만이 walkable하도록 만든다.
이후 Collision Testing을 살펴볼 것이다.
기본적으로 Collider type, Offset, Obstacle Layer Mask로 구성돼있다.
이외 Diameter, Height/Length등의 파라미터는 Collider type에 따라 달라지게 된다.
(※ Sphere는 Diameter만 존재, Ray는 Height/Length만 존재)
- Collider type : Sphere, Capsule, Ray등 3가지 타입 존재. 보통 Capsule 사용
- Diameter : 지름, 해당 게임에서 돌아다닐 AI의 크기로 지정
- Height/Length : 높이, 위와 마찬가지
(※ 이 두 파라미터 값은 AI 크기보단 크게, 넉넉하게 잡는것이 좋다.)
- Offset : AI가 Ground에서부터 얼마나 높이 떨어져있는지
- Obstacle Layer Mask : 갈 수 없는 Layer Mask 지정
이제 각 파라미터가 바뀔때마다 어떻게 변할 것인지 확인할 것이다.
기본적으로 Obstacle Layer Mask는 "Wall"과 "Obstacle"로 지정하였다.
먼저 현재 상태로 Scan을 하면, 아래와 같은 형태로 나타난다.
(※ Obstacle Layer Mask를 지정하면서 Wall과 Obstacle의 파란색을 칠해져있던 윗부분이 없어진 것을 확인할 수 있다.)
Diameter를 2로 늘리면, 갈 수 있는 영역이 좀 줄어드는 것을 확인할 수 있다.(∵ AI의 몸집이 커지므로)
그다음 Height/Length를 조절할 것인데, 해당 지형에서는 AI의 키가 커봤자 못가는 지형이 생기는 것은 아니라서, 아무리 늘려봤자 변하는 것이 없다.
따라서 키가 큰 AI는 못지나가도록 지형을 아래와 같이 변경해주자.(※ 추가한 Cube에 "Obstacle" Layer를 지정해야 함)
이 상태로 Scan시, 아래와 같이 Graph가 형성된다.
마지막으로 Offset을 조절해보자.
아마 Offset은 공중 위를 날아다니는 AI를 위한 파라미터인것 같다.
대충 Wall 위에 떠 있는 흰색 Cube보다 높게 설정하면, 갈 수 없던 곳이 갈 수 있는 것으로 바뀌는 것을 확인할 수 있다
파라미터 값을 극단적으로 높여보며 차이점을 살펴봤으니, 다시 정상적으로 돌려놓는다.
3. 움직일 AI 만들기
1) GameObject 만들고 이동 스크립트 추가
먼저 GameObject를 만들고 [3D Object] - [Capsule]을 만들어 만든 GameObject에 붙인다.
만든 GameObject의 이름은 "AI"라고 지었다.
그 후 AI에 이동 스크립트를 추가한다.
이때 이동 스크립트는 AIPath, RichAI, AILerp등 3가지 종류가 존재한다.
- AIPath : 기본적인 이동 스크립트, 모든 Graph에서 사용 가능
- RichAI : Navmesh 기반 Graph용 (무료 버전엔 없음)
- AILerp : 선형 보간법을 통해 정확한 경로 계산, 모든 Graph에서 사용 가능
이 중 대표적으로 사용하는 AIPath Component를 추가한다.
AIPath를 추가함에 따라 생기는 AI의 collider안에 Capsule이 들어가도록 아래와 같이 position을 조절해야한다.
추가하게 되면 AIPath 이외에도 Seeker라는 스크립트도 추가된다.
이는 Helper Script인데, 대충 AIPath가 어느 지점으로 가고 싶다는 것을 Seeker에게 전달하면,
Seeker가 A*의 Pathfinder Component를 보고 경로를 계산하는 Script라고 보면 된다.
Seeker에 여러 요소가 있는데, 음... 다음에 알아보자
AIPath는 아래와 같이 구성돼있다.
크게 Shape, Pathfinding, Movement로 구성돼있는데, 각각에 대해 간략히 설명하면
- Shape : 노란색 원통형 collider 크기
- Radius : 반지름 결정
- Height : 높이 결정
- Pathfinding : 목적지까지 path 찾는 주기 설정
- Recalculate paths automatically : Dynamic, Never, Every N Seconds로 구성, 기본적으로 동적으로 찾아주는 Dynamic 사용
- Maximum Period : path 재설정하는 최대 주기(Dynamic에만 존재)
- Sensitivity : 주변 감지할 범위(Dynamic에만 존재)
- Visualize Sensitivity : 게임 실행 시 Scene상에서 Sensitivity 보이게끔 할 것인지 여부(Dynamic에만 존재)
- Movement
- Can Move : 움직일 수 있는지 여부, 미체크시 움직이지 않음
- Max Speed : 목표까지 갈 때 낼 수 있는 최대 Speed, 높을수록 빠름
- Max Acceleration : 가속/감속 단위, 높을수록 속도가 빨리 빨라지고 빨리 느려짐. (※ Default로 설정할 시, Max Speed와 동일한 값인듯함)
- Orientation : 방향축 관련, 3D 게임은 ZAxisForward, 2D 게임은 YAxisForward로 설정
- Enable Roatation : 방향 틀때 몸 회전 여부, 미체크시 방향을 틀어도 몸이 회전하지 않음
- Pick Next Waypoint Distance : 계산한 경로에서 waypoint을 잡는 범위(※ 아래 그림 참고)
- Slowdown Distance : 감속을 시작할 목적지까지의 거리
- End Reached Distance : 도착했음을 판단할 목적지까지의 거리
- Always Draw Gizmos : 위 3개 Distance의 범위를 Scene상에서 표현할 것인지 유무
- When Close To Destination : Stop, Continue To Exact Destination 옵션 존재
- Constrain Inside Graph : ??
- Gravity : 중력 설정
- Debug info : 목적지까지와의 거리, 목적지 좌표등 포함
2) AI Destination Setter 추가
위에서 이동 스크립트를 추가하면서 AI가 이동하는 방법을 익혔다면, 이제 이동할 목적지를 설정해줘야한다.
이는 AI에 "AI Destination Setter" Component를 추가해야하며, 해당 Component는 아래와 같이 구성된다.
사용법은 엄청 간단한데, Target에 목적지가 될 빈 GameObject를 만들어 넣으면 된다.
즉 GameObject의 위치가 AI가 움직일 목적지가 된다는 뜻이다.
무튼 Target을 넣어서 아래와 같이 만든다.
진짜 실행해서 테스트해보기 위해 Target과 AI를 아래와 같이 배치한다.
실행하면 제대로 path가 나오면서 자동으로 이동하는 것을 확인할 수 있다!!!!
참고자료