방황하는 AI를 만드는 방법에 대한 튜토리얼.

방황하는 AI를 만드는 방법에는 여러 가지가 있습니다. 이 방법들은 품질과 성능 면에서 차이가 있습니다. 명확한 최선의 해결책은 없으며, 각 방법은 게임에 따라 더 적합할 수 있습니다. 각 방법에 대해 장점과 단점을 나열했습니다.

  • 방법 1: 원 안의 무작위 지점
  • 방법 2: 전체 그래프에서 무작위 노드
  • 방법 3: RandomPath 유형
  • 방법 4: ConstantPath 유형
  • 방법 5: 너비 우선 탐색

방법 1: 원 안의 무작위 지점
이 방법은 캐릭터 주위의 특정 거리 내에서 무작위 지점을 선택하는 가장 간단한 방법입니다.

 

방법 1: 원 안의 무작위 지점

이동할 지점을 선택하는 가장 쉬운 방법은 캐릭터 주위의 특정 거리 내에서 무작위 지점을 선택하는 것입니다.

Vector3 PickRandomPoint () {
    var point = Random.insideUnitSphere * radius;

    point.y = 0;
    point += transform.position;
    return point;
}

포함된 이동 스크립트 중 하나를 사용하는 경우, 예를 들어 AI가 현재 경로의 끝에 도달할 때마다 목적지를 변경할 수 있습니다.

using UnityEngine;
using System.Collections;
using Pathfinding;

public class WanderingDestinationSetter : MonoBehaviour {
    public float radius = 20;

    IAstarAI ai;

    void Start () {
        ai = GetComponent<IAstarAI>();
    }

    Vector3 PickRandomPoint () {
        var point = Random.insideUnitSphere * radius;

        point.y = 0;
        point += ai.position;
        return point;
    }

    void Update () {
        // AI의 목적지를 업데이트합니다.
	// AI가 경로를 계산 중이 아니고
	// AI가 경로의 끝에 도달했거나 경로가 전혀 없을 때
        if (!ai.pathPending && (ai.reachedEndOfPath || !ai.hasPath)) {
            ai.destination = PickRandomPoint();
            ai.SearchPath();
        }
    }
}

위의 스크립트를 AIPath, RichAI, AILerp 등의 내장 이동 스크립트가 포함된 어떤 게임 오브젝트에든 부착할 수 있습니다.

참고
AI의 목적지를 설정하려고 시도하는 다른 컴포넌트( AIDestinationSetter 컴포넌트 등)가 부착되어 있지 않은지 확인하십시오.

 

 

 

참조
Pathfinding.IAstarAI
Random.insideUnitSphere

 

 

장점

  • 매우 빠름.
  • 간단한 코드.
  • 모든 그래프 유형에서 비교적 잘 작동함.

단점

  • 지점까지의 실제 거리를 무시하므로, 세계가 매우 개방적이지 않은 경우 매우 긴 경로를 생성할 수 있음(위의 비디오 참조).
  • 장애물 내부에서 생성된 지점은 그래프의 가장 가까운 지점으로 이동해야 하므로, 벽이나 장애물 근처의 지점으로 약간의 편향이 있음.

기타

  • 지점을 선택할 때 패널티를 무시함(그러나 지점까지 경로를 찾을 때는 패널티가 고려됨).

 

방법 2: 전체 그래프에서 무작위 노드

때로는 매우 간단한 것을 원할 때가 있습니다. 현재 위치 주위의 노드를 선택하는 대신, 그래프에서 무작위 노드를 선택하고 해당 노드의 위치로 이동하려고 시도할 수 있습니다.

GraphNode randomNode;

// 그리드 그래프의 경우
var grid = AstarPath.active.data.gridGraph;

randomNode = grid.nodes[Random.Range(0, grid.nodes.Length)];

// 포인트 그래프의 경우
var pointGraph = AstarPath.active.data.pointGraph;
randomNode = pointGraph.nodes[Random.Range(0, pointGraph.nodes.Length)];

// 모든 그래프 유형에서 작동하지만 훨씬 느림
var graph = AstarPath.active.data.graphs[0];
// 그래프의 모든 노드를 리스트에 추가
List<GraphNode> nodes = new List<GraphNode>();
graph.GetNodes((System.Action<GraphNode>)nodes.Add);
randomNode = nodes[Random.Range(0, nodes.Count)];

// 예를 들어 노드의 중심을 목적지로 사용
var destination1 = (Vector3)randomNode.position;
// 또는 노드 표면의 무작위 지점을 목적지로 사용
// 이는 노드가 큰 네비게이션 메시 기반 그래프에서 유용함
var destination2 = randomNode.RandomPointOnSurface();

 

 

사용 용도에 따라, 노드를 선택한 후 다음과 같은 체크를 수행할 수 있습니다:

  • 노드가 걷기 가능한지 확인 (  Pathfinding.GraphNode.Walkable 참조)
  • 노드가 AI로부터 도달 가능한지 확인 (  Pathfinding.PathUtilities.IsPathPossible 참조)
  • 게임에 관련된 다른 체크 사항. 이 체크 중 하나가 실패하면 새로운 무작위 노드를 선택하고 다시 체크를 수행할 수 있습니다. 유효한 노드가 매우 드물지 않은 한 유효한 노드를 빠르게 찾을 수 있을 것입니다.

장점

  • 매우 빠름 (위의 일반적인 접근 방식을 사용하지 않는 경우)
  • 간단한 코드

단점

  • 경로 길이에 대한 제어가 거의 없음

기타

  • 지점을 선택할 때 패널티를 무시함 (그러나 지점까지 경로를 찾을 때는 패널티가 고려됨).

 

방법 3: RandomPath 유형

RandomPath 유형은 특정 지점에서 다른 특정 지점으로의 경로를 계산하는 일반적인 경로와는 달리, 시작 지점에서부터 랜덤하게 멀어지는 경로를 계산하는 경로 유형입니다.

내장된 이동 스크립트 중 하나를 사용하고 있다면 ( Movement scripts 참조) 다음과 같은 작업을 수행할 수 있습니다:

// 에이전트의 내부 자동 경로 재계산을 비활성화합니다
ai.canSearch = false;
RandomPath path = RandomPath.Construct(transform.position, searchLength);
path.spread = spread;
// 에이전트에게 계산하고 따라갈 경로를 지정합니다
ai.SetPath(path);

 

사용자 정의 이동 스크립트를 사용하는 경우, 이를 수동으로 시커(Seeker)에 전달해야 합니다.

RandomPath path = RandomPath.Construct(transform.position, searchLength);

path.spread = spread;
seeker.StartPath(path);
Searching for paths  참조

 

 

장점

  • 한 번에 지점을 선택하고 경로를 계산함.
  • 고려되는 모든 노드가 동일한 확률로 선택되므로, 방법 1: 원 안의 무작위 지점과 달리 장애물 근처에 대한 편향이 없음.
  • 최소 경로 비용을 설정할 수 있음(searchLength).

 

단점

  • 긴 경로의 경우 속도가 느릴 수 있음.
  • 모든 노드가 동일한 확률로 선택되므로, 디테일이 많은 지역(더 많고 작은 노드가 있는 지역)에 대한 편향이 발생하여 navmesh/recast 그래프에서 잘 작동하지 않음.

 

기타

패널티를 고려함.

 

Pathfinding.RandomPath  참조

 

 

방법 4: ConstantPath 유형

ConstantPath 유형은 시작 지점에서 특정 값과 같거나 그 이하의 비용으로 도달할 수 있는 모든 노드를 찾는 경로 유형입니다. 이러한 모든 노드를 찾은 후, 해당 노드 표면에서 하나 이상의 무작위 지점을 선택할 수 있습니다.

ConstantPath path = ConstantPath.Construct(transform.position, searchLength);

AstarPath.StartPath(path);
path.BlockUntilCalculated();
var singleRandomPoint = PathUtilities.GetPointsOnNodes(path.allNodes, 1)[0];
var multipleRandomPoints = PathUtilities.GetPointsOnNodes(path.allNodes, 100);

 

내장된 이동 스크립트에 이를 적용하려면, 방법 1: 원 안의 무작위 지점에서 사용한 것과 동일한 접근 방식을 사용할 수 있습니다.

 

참조
Pathfinding.ConstantPath
Pathfinding.PathUtilities.GetPointsOnNodes

 

장점

  • 단일 경로 요청으로 여러 무작위 지점을 선택할 수 있음.
  • 노드를 선택할 확률은 해당 노드의 표면적에 비례함 (따라서 모든 노드가 동일한 크기를 갖는 경우, 예를 들어 그리드 그래프를 사용할 때, 고려되는 모든 노드는 동일한 확률로 선택됨). 방법 1: 원 안의 무작위 지점처럼 장애물 근처에 대한 편향이 없음.
  • 필요할 경우 노드의 사용자 정의 필터링이 가능함.
  • 방법 3: RandomPath 유형보다 보통 약간 더 빠름.
  • navmesh/recast 그래프에서 비교적 잘 작동함.

 

단점

  • 많은 노드를 검색해야 할 때 느릴 수 있음.

 

기타

  • 패널티를 고려함.

 

방법 5: 너비 우선 탐색

 breadth-first search은 시작 노드에서부터 하나의 노드씩 외부로 검색하는 간단한 탐색 방법입니다. 패널티나 다른 유형의 비용을 고려하지 않습니다. 예를 들어, 그리드 그래프에서 대각선으로 이동하는 것이 4개의 비대각선 연결 중 하나를 따라 이동하는 것과 동일한 비용을 가진다는 의미입니다.

사용 방법은 방법 4: ConstantPath 유형에서 사용된 것과 매우 유사합니다.

// 가장 가까운 걷기 가능한 노드 찾기
var startNode = AstarPath.active.GetNearest(transform.position, NNConstraint.Walkable).node;
var nodes = PathUtilities.BFS(startNode, nodeDistance);
var singleRandomPoint = PathUtilities.GetPointsOnNodes(nodes, 1)[0];
var multipleRandomPoints = PathUtilities.GetPointsOnNodes(nodes, 100);

내장된 이동 스크립트에 이를 적용하려면, 방법 1: 원 안의 무작위 지점에서 사용한 것과 동일한 접근 방식을 사용할 수 있습니다.

 

참조
Pathfinding.PathUtilities.BFS
Pathfinding.PathUtilities.GetPointsOnNodes

 

장점

  • 하나의 지점뿐만 아니라 여러 무작위 지점을 선택할 수 있음.
  • 노드를 선택할 확률은 해당 노드의 표면적에 비례함(따라서 모든 노드가 동일한 크기를 갖는 경우, 예를 들어 그리드 그래프를 사용할 때, 고려되는 모든 노드는 동일한 확률로 선택됨). 방법 1: 원 안의 무작위 지점처럼 장애물 근처에 대한 편향이 없음.
  • 필요할 경우 나중에 노드를 사용자 정의 필터링할 수 있음.
  • 경로 찾기 시스템으로의 왕복이 필요 없으므로 약간의 오버헤드를 줄일 수 있음.
  • 보통 방법 4: ConstantPath 유형과 방법 3: RandomPath 유형보다 약간 더 빠름.

단점

  • 많은 노드를 검색해야 할 때 느릴 수 있음.
  • 경로 찾기 스레드를 사용하지 않으므로, 이를 Unity 메인 스레드에서 쉽게 오프로드할 수 있는 기능을 잃게 됨.
  • navmesh/recast 그래프에서는 특히 잘 작동하지 않음. 노드의 크기와 세부 사항에 따라 경로 길이가 크게 달라지기 때문임(노드가 많고 작을수록 BFS가 멀리 도달하지 못함).

기타

  • 패널티나 다른 비용을 고려하지 않으며, 탐색된 노드의 수만 중요함.

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

Agent-Specific Pathfinding  (0) 2024.05.25
Multiple agent types  (0) 2024.05.25
Local Avoidance > Custom Local Avoidance Movement Script  (0) 2024.05.25
Local Avoidance  (0) 2024.05.25
Using Modifiers  (0) 2024.05.24

+ Recent posts