노드 사용 방법 소개

경로 찾기는 노드 그래프에서 수행됩니다. 이 노드들은 다양한 방식으로 서로 연결됩니다. 그리드에서는 각 타일이 하나의 노드이며, 4개 또는 8개의 인접 타일과 연결됩니다. 내브메시/리캐스트 그래프에서는 각 삼각형이 하나의 노드이며, 노드들은 삼각형의 중심에 위치합니다.


전체 검색 알고리즘이 작동하는 방식을 설명하는 것은 이 튜토리얼의 범위를 벗어납니다. 하지만 여기 Wikipedia의 멋진 애니메이션이 있습니다:

 

참조
Graph Updates.
Accessing graph data

 

Finding Nodes close to Positions

종종 세계의 한 지점에 가장 가까운 노드가 무엇인지 알아내고 싶을 때가 있습니다. 기본 이동 스크립트를 사용하는 경우 노드와 전혀 상관없지만, 더 깊이 들어가면 매우 유용해집니다.

// 이 게임 오브젝트의 위치에 가장 가까운 노드를 찾습니다.
GraphNode node = AstarPath.active.GetNearest(transform.position).node;

if (node.Walkable) {
    // 와우, 노드가 이동 가능하네요. 여기다 타워를 놓을 수 있습니다.
}

특정 노드만 가져와야 하는 경우도 있습니다. 예를 들어 "이 위치에서 가장 가까운 *이동 가능한* 노드는 무엇인가?"와 같은 경우입니다. 이는 NNConstraint 클래스를 사용하여 해결할 수 있습니다. 이 경우 Default NNConstraint를 사용할 수 있습니다(기본이라고 불리는 이유는 다른 것이 지정되지 않은 경우 경로 호출에 사용되기 때문입니다).

GraphNode node = AstarPath.active.GetNearest(transform.position, NNConstraint.Walkable).node;

맞춤 제약 조건을 생성할 수도 있습니다:

var constraint = NNConstraint.None;

// 검색을 이동 가능한 노드로만 제한합니다.
constraint.constrainWalkability = true;
constraint.walkable = true;

// 검색을 태그 3 또는 태그 5가 있는 노드로만 제한합니다.
// 'tags' 필드는 비트마스크입니다.
constraint.constrainTags = true;
constraint.tags = (1 << 3) | (1 << 5);

var info = AstarPath.active.GetNearest(transform.position, constraint);
var node = info.node;
var closestPoint = info.position;

이러한 제약 조건의 검색 범위는 무한하지 않지만 상당히 큽니다. 최대 거리는 A* Inspector -> Settings -> Max Nearest Node Distance 또는  AstarPath.maxNearestNodeDistance 에서 설정할 수 있습니다. 가장 가까운 노드가 'Max Nearest Node Distance'보다 멀리 있으면 `GetNearest` 메서드는 null 노드를 반환합니다.

참고
 Pathfinding.NNConstraint 클래스에는 더 많은 옵션이 있으므로 필요에 따라 확인해보십시오.

 

Closest Point on Nodes

위에서 `GetNearest` 호출로부터 노드를 가져오기 위해 `node` 필드에 접근해야 한다는 점을 눈치챘을 것입니다. `GetNearest` 메서드는  NNInfo 구조체를 반환하며, 이 구조체에는 두 개의 필드가 있습니다. 첫 번째는  node  필드로, 가장 적합한 노드를 포함하고 있습니다(노드를 찾을 수 없는 경우 null이 됩니다). 두 번째는  position 필드로, 쿼리 지점에서 해당 노드의 가장 가까운 점을 포함하고 있습니다. 그리드 그래프에서는 노드를 사각형으로 간주하므로 `position` 필드는 쿼리 지점에서 해당 사각형 내의 가장 가까운 점을 포함하게 됩니다. 내브메시 기반 그래프(RecastGraph 및 NavMeshGraph)에서는 `position` 필드가 가장 가까운 삼각형에서 가장 가까운 점을 포함하게 됩니다. 포인트 노드는 표면이 없으므로 `position`은 노드의 위치로 설정됩니다.

var info = AstarPath.active.GetNearest(transform.position);
var node = info.node;
var closestPoint = info.position;

 

Node connections

각 노드는 연결된 다른 노드를 저장합니다. 이것이 표현되는 방식은 그래프에 따라 다릅니다. 예를 들어, 그리드 그래프는 그리드 구조를 활용하여 인접한 그리드 노드들에 대한 모든 연결을 단 하나의 바이트로 저장할 수 있습니다! 이는 예를 들어 다른 노드들에 대한 참조 배열을 사용하는 것보다 최소 80배 더 메모리 효율적입니다.

노드의 모든 연결에 접근하려면  GetConnection 메서드를 사용할 수 있습니다. 이 메서드는 각 연결된 노드에 대해 호출되는 대리자를 매개변수로 받으며, 기본 표현을 추상화합니다.

GraphNode node = ...;
// 연결된 모든 노드에 선을 그리세요.
node.GetConnections(otherNode => {
    Debug.DrawLine((Vector3)node.position, (Vector3)otherNode.position);
});
노드에서 사용자 정의 연결을 추가하거나 제거할 수도 있습니다. 자세한 내용은 그래프 생성기 작성( Writing Graph Generators )을 참조하십시오.

 

Node properties

노드 인스턴스에는 몇 가지 흥미로운 메서드가 있습니다.

첫째, 노드에는 월드 공간에서의 노드 위치를 나타내는 position 필드가 있습니다. 이 위치는 `Vector3`가 아닌 `Int3`로 저장됩니다. 그러나 `Vector3`와 `Int3` 간의 변환은 쉽게 할 수 있습니다.

GraphNode node = ...;
Vector3 v3position = (Vector3)node.position;
node.position = (Int3)v3position;

노드에서 다양한 속성에 접근할 수도 있습니다. 예를 들어, 노드가 이동 가능한지 여부, 태그, 패널티 등이 있습니다.

bool walkable = node.Walkable;
uint tag = node.Tag;
uint penalty = node.Penalty;

 

확인
노드의 속성을 변경하는 방법에 대해 더 알고 싶다면 그래프 업데이트( Graph Updates )를 참조하십시오.


노드에서 점을 찾기 위한 몇 가지 유틸리티 메서드도 있습니다.
노드 표면에서 임의의 점을 얻을 수 있습니다:

Vector3 randomPoint = node.RandomPointOnSurface();

그리고 노드의 표면적을 얻을 수 있습니다(포인트 노드의 경우 이는 0이 됩니다):

float surfaceArea = node.SurfaceArea();

 

TriangleMeshNode

메시 노드는 내브메시 및 리캐스트 그래프에서 사용됩니다.

참고: 
그래프 유형( Graph Types )을 참조하십시오.

이 노드에는 몇 가지 추가 유틸리티가 있습니다. 특정 노드에서 가장 가까운 지점을 얻을 수 있습니다. XZ 공간(즉, 위에서 본 것처럼)이나 3D 공간에서 가장 가까운 지점을 얻을 수 있습니다.

MeshNode node = ...;
Vector3 closestPoint = node.ClosestPointOnNode(somePoint);
Vector3 closestPoint = node.ClosestPointOnNodeXZ(somePoint);

특정 지점이 해당 노드 내부에 있는지(위에서 본 경우) 확인할 수도 있습니다.

if (node.ContainsPoint(somePoint)) {
    // 해당 지점이 노드 내부에 있습니다.
}

해당 노드가 나타내는 삼각형의 정점을 얻을 수 있습니다:

// 개별적으로
Int3 v0 = node.GetVertex(0);
Int3 v1 = node.GetVertex(1);
Int3 v2 = node.GetVertex(2);
// 또는 결합하여 얻을 수 있습니다(더 빠름).
Int3 v0, v1, v2;
node.GetVertices(out v0, out v1, out v2);

 

 

Reachability

종종 캐릭터가 특정 노드에 도달할 수 있는지 여부를 판단하는 것이 유용합니다. 경로가 계산될 때 기본적으로 도달할 수 있는 대상에 가장 가까운 노드로 이동하려고 한다는 점을 유념하세요(앞서 논의한 AstarPath.maxNearestNodeDistance 까지의 최대 거리). 따라서 종종 이에 대해 걱정할 필요가 없습니다.

경로 찾기 시스템은 그래프의 연 connected components 를 계산하여 어떤 노드에서 다른 노드로 도달할 수 있는지 미리 계산합니다. 이는 장면 뷰에서 다양한 색상으로 표시됩니다(그래프 색상 옵션이 'Areas'로 설정된 경우). 각 노드의 Area 필드는 해당 연결된 구성 요소의 인덱스로 설정됩니다. 두 노드가 동일한 영역을 가지고 있다면, 그 사이에 유효한 경로가 있음을 의미합니다. 이를  PathUtilities.IsPathPossible 메서드를 사용하여 확인할 수도 있습니다.

var node1 = AstarPath.active.GetNearest(somePoint1);
var node2 = AstarPath.active.GetNearest(somePoint2);
if (PathUtilities.IsPathPossible(node1, node2)) {
    // 노드들 사이에 유효한 경로가 있습니다.
}

이 영역 또는 연결된 구성 요소를 계산하는 과정을 문서와 코드의 여러 부분에서는 'flood filling'이라고 합니다.

또한 IsPathPossible 메서드에 태그 마스크나 노드 목록을 제공할 수도 있습니다.

참고: 
Pathfinding.PathUtilities

주어진 노드로부터 도달할 수 있는 모든 노드를 찾을 수도 있습니다.

List<GraphNode> reachableNodes = PathUtilities.GetReachableNodes(node);
참고
특정 노드로부터 특정 거리까지의 모든 노드를 찾는 여러 가지 방법도 있습니다. 자세한 내용은 Wandering AI Tutorial 을 참조하십시오.

'유니티 에셋 > A* Pathfinding project pro' 카테고리의 다른 글

Working with tags  (0) 2024.05.27
Navmesh Cutting  (0) 2024.05.27
Grid Graph Rules > Writing Custom Grid Graph Rules  (0) 2024.05.26
Grid Graph Rules  (0) 2024.05.26
Graph Updates during Runtime  (0) 2024.05.26

+ Recent posts