Hey, everybody!
I am creating a 2D top-down game, the action in which takes place in a 2D maze.
Chose Astar Pathfinding to create AI enemies in my game (I’m pretty weak at this fr). Its purpose is to help enemies navigate the maze and find the player
I created a prototype with pre-drawn walls, character and enemies
Have checked the path creation with debug.log and the path list is created, but the problem is that the coordinates of the created nodes are incredibly far from the scene, for example the x coordinate of a node may be 2000 and the y coordinate may be 1000. As I understand it, this is because I am applying screen height and width when calculating the width and height of each cell in this part of the code:
private void MakeaGrid()
{
int cellwidth = camera.pixelWidth / gridwidth;
int cellheight = camera.pixelHeight / gridheight;
Vector3 bottomLeftCorner = camera.ScreenToWorldPoint(Vector3.zero);
float minX = bottomLeftCorner.x;
float minY = bottomLeftCorner.y;
grid = new Node[gridwidth, gridheight];
for (int x = 0; x < gridwidth; x++)
{
for (int y = 0; y < gridheight; y++)
{
int cellPosX = x * cellwidth + (int)minX;
int cellPosY = (gridheight - y - 1) * cellheight + (int)minY;
bool isWalkable = !Physics2D.OverlapBox(new Vector2(cellPosX, cellPosY), new Vector2(cellwidth, cellheight), 0f, wall);
grid[x, y] = new Node(cellPosX, cellPosY, isWalkable);
}
}
}
Please help me to solve the problem so that nodes are created inside the scene, on the maze.
I’ll also attach all my code. Perhaps there are errors there as well. Please review it, if it’s not too much trouble
public class astar : MonoBehaviour
{
public LayerMask wall;
public new Camera camera;
public int gridwidth;
public int gridheight;
private Node[,] grid;
public Transform player;
private int currentWaypointIndex = 0;
void Start()
{
camera = Camera.main;
MakeaGrid();
Node node1 = new Node(1, 2, true);
Node node2 = new Node(3, 4, false);
FindPath(node1, node2);
}
void Update()
{
Vector3 targetpos = player.position;
Vector3 startpos = transform.position;
Node target = new Node(Mathf.FloorToInt(targetpos.x), Mathf.FloorToInt(targetpos.y), true);
Node start = new Node(Mathf.FloorToInt(startpos.x), Mathf.FloorToInt(startpos.y), true);
List<Node> Path = FindPath(start, target);
if (Path != null && currentWaypointIndex < Path.Count)
{
Node currentWaypoint = Path[currentWaypointIndex];
Vector3 targetPosition = new Vector3(currentWaypoint.x, currentWaypoint.y, 0);
float moveSpeed = 5f;
transform.position = Vector3.MoveTowards(transform.position, targetPosition, moveSpeed * Time.deltaTime);
if (Vector3.Distance(transform.position, targetPosition) < 0.01f)
{
currentWaypointIndex++;
}
}
}
private void MakeaGrid()
{
int cellwidth = camera.pixelWidth / gridwidth;
int cellheight = camera.pixelHeight / gridheight;
Vector3 bottomLeftCorner = camera.ScreenToWorldPoint(Vector3.zero);
float minX = bottomLeftCorner.x;
float minY = bottomLeftCorner.y;
grid = new Node[gridwidth, gridheight];
for (int x = 0; x < gridwidth; x++)
{
for (int y = 0; y < gridheight; y++)
{
int cellPosX = x * cellwidth + (int)minX;
int cellPosY = (gridheight - y - 1) * cellheight + (int)minY;
bool isWalkable = !Physics2D.OverlapBox(new Vector2(cellPosX, cellPosY), new Vector2(cellwidth, cellheight), 0f, wall);
Debug.Log("ширина =" + cellwidth + "высота =" + cellheight);
grid[x, y] = new Node(cellPosX, cellPosY, isWalkable);
Debug.Log("ширина ячейки =" + cellwidth + "высота ячейки =" + cellheight);
Debug.Log("путь по x =" + cellPosX + "путь по y =" + cellPosY);
}
}
}
private List<Node> FindPath(Node start, Node target)
{
start.gCost = 0;
List<Node> openList = new List<Node>();
HashSet<Node> closedList = new HashSet<Node>();
openList.Add(start);
while (openList.Count > 0)
{
Node currentNode = openList[0];
for (int i = 1; i < openList.Count; i++)
{
if (openList[i].fCost < currentNode.fCost || openList[i].fCost == currentNode.fCost && openList[i].hCost < currentNode.hCost)
{
currentNode = openList[i];
}
}
openList.Remove(currentNode);
closedList.Add(currentNode);
if (currentNode == target)
{
return RetracePath(start, target);
}
foreach (Node neighbor in GetNeighbors(currentNode))
{
if (!neighbor.isWalkable || closedList.Contains(neighbor))
{
continue;
}
float newMovementCostToNeighbor = currentNode.gCost + GetDistance(currentNode, neighbor);
if (newMovementCostToNeighbor < neighbor.gCost || !openList.Contains(neighbor))
{
neighbor.gCost = newMovementCostToNeighbor;
neighbor.hCost = GetDistance(neighbor, target);
neighbor.fCost = neighbor.gCost + neighbor.hCost;
neighbor.parent = currentNode;
if (!openList.Contains(neighbor))
{
openList.Add(neighbor);
}
}
}
}
return null;
}
private List<Node> RetracePath(Node start, Node target)
{
List<Node> path = new List<Node>();
Node currentNode = target;
while (currentNode != start)
{
path.Add(currentNode);
currentNode = currentNode.parent;
}
path.Reverse();
return path;
}
float GetDistance(Node nodeA, Node nodeB)
{
if (!nodeA.isWalkable || !nodeB.isWalkable)
{
return int.MaxValue;
}
float dstX = Mathf.Abs(nodeA.x - nodeB.x);
float dstY = Mathf.Abs(nodeA.y - nodeB.y);
return dstX + dstY;
}
List<Node> GetNeighbors(Node node)
{
List<Node> neighbors = new List<Node>();
int[] xOffset = { -1, 1, 0, 0 };
int[] yOffset = { 0, 0, -1, 1 };
for (int i = 0; i < 4; i++)
{
int neighborX = node.x + xOffset[i];
int neighborY = node.y + yOffset[i];
if (neighborX >= 0 && neighborX < gridwidth &&
neighborY >= 0 && neighborY < gridheight)
{
Node neighbor = grid[neighborX, neighborY];
if (neighbor.isWalkable)
{
neighbors.Add(neighbor);
}
}
}
return neighbors;
}
public class Node
{
public int x;
public int y;
public bool isWalkable;
public float gCost = float.MaxValue;
public float hCost;
public float fCost;
public Node parent;
public Node(int x, int y, bool isWalkable)
{
this.x = x;
this.y = y;
this.isWalkable = isWalkable;
}
}
}