반응형
- 코드 작성
using UnityEngine;
using System.Collections.Generic;
public class Pathfinding : MonoBehaviour
{
public Transform seeker; // 시작 위치
public Transform target; // 목표 위치
public LayerMask obstacleMask;
public float nodeRadius = 0.5f;
private Node startNode;
private Node targetNode;
private void Start()
{
// 시작 및 목표 경로를 위치를 기반으로 찾기
startNode = NodeFromWorldPoint(seeker.position);
targetNode = NodeFromWorldPoint(target.position);
// 경로를 찾아 저장
List<Node> path = FindPath(startNode, targetNode);
}
// 경로를 찾기
List<Node> FindPath(Node startNode, Node targetNode)
{
List<Node> openSet = new List<Node>();
HashSet<Node> closedSet = new HashSet<Node>();
openSet.Add(startNode);
while (openSet.Count > 0)
{
Node currentNode = openSet[0];
for (int i = 1; i < openSet.Count; i++)
{
if (openSet[i].fCost < currentNode.fCost || openSet[i].fCost == currentNode.fCost && openSet[i].hCost < currentNode.hCost)
{
currentNode = openSet[i];
}
}
openSet.Remove(currentNode);
closedSet.Add(currentNode);
if (currentNode == targetNode)
{
return RetracePath(startNode, targetNode);
}
foreach (Node neighbor in GetNeighbors(currentNode))
{
if (!neighbor.walkable || closedSet.Contains(neighbor))
{
continue;
}
int newMovementCostToNeighbor = currentNode.gCost + GetDistance(currentNode, neighbor);
if (newMovementCostToNeighbor < neighbor.gCost || !openSet.Contains(neighbor))
{
neighbor.gCost = newMovementCostToNeighbor;
neighbor.hCost = GetDistance(neighbor, targetNode);
neighbor.parent = currentNode;
if (!openSet.Contains(neighbor))
{
openSet.Add(neighbor);
}
}
}
}
return null;
}
// 경로 추적
List<Node> RetracePath(Node startNode, Node endNode)
{
List<Node> path = new List<Node>();
Node currentNode = endNode;
while (currentNode != startNode)
{
path.Add(currentNode);
currentNode = currentNode.parent;
}
path.Reverse();
return path;
}
// 주변 좌표 얻기
List<Node> GetNeighbors(Node node)
{
List<Node> neighbors = new List<Node>();
for (int x = -1; x <= 1; x++)
{
for (int y = -1; y <= 1; y++)
{
if (x == 0 && y == 0)
{
continue;
}
int checkX = node.gridX + x;
int checkY = node.gridY + y;
if (checkX >= 0 && checkX < GridManager.instance.gridSizeX && checkY >= 0 && checkY < GridManager.instance.gridSizeY)
{
neighbors.Add(GridManager.instance.grid[checkX, checkY]);
}
}
}
return neighbors;
}
// 두 지점 사이의 거리
int GetDistance(Node nodeA, Node nodeB)
{
int dstX = Mathf.Abs(nodeA.gridX - nodeB.gridX);
int dstY = Mathf.Abs(nodeA.gridY - nodeB.gridY);
return dstX + dstY;
}
// 월드 좌표에서 지점 좌표 얻기
Node NodeFromWorldPoint(Vector3 worldPosition)
{
float percentX = (worldPosition.x + GridManager.instance.gridWorldSize.x / 2) / GridManager.instance.gridWorldSize.x;
float percentY = (worldPosition.z + GridManager.instance.gridWorldSize.y / 2) / GridManager.instance.gridWorldSize.y;
percentX = Mathf.Clamp01(percentX);
percentY = Mathf.Clamp01(percentY);
int x = Mathf.FloorToInt((GridManager.instance.gridSizeX - 1) * percentX);
int y = Mathf.FloorToInt((GridManager.instance.gridSizeY - 1) * percentY);
return GridManager.instance.grid[x, y];
}
}
반응형