Unity A星寻路算法演示

本文介绍如何在Unity中实现A星寻路算法,并通过代码演示其工作原理。提供了AStar.cs和AStarTest.cs两个关键脚本,用于寻路逻辑和模拟演示。读者可以下载Unity工程进行实践,理解A星算法在游戏场景中的应用。
摘要由CSDN通过智能技术生成

>>实现简单A星寻路,并且用Unity模拟演示<<

 

算法原理这里就不再赘述了,网上一大推.我也是参考的https://www.cnblogs.com/lipan/archive/2010/07/01/1769420.html的算法

先上代码---------------------------->>>>>>>>>>>>>>>>

using System;
using System.Collections;
using System.Collections.Generic;

//参考的https://www.cnblogs.com/lipan/archive/2010/07/01/1769420.html的算法

/*寻路算法*/
class AStar
{
    //开表
    List<Point> open_List = new List<Point>();

    //闭表
    List<Point> close_List = new List<Point>();

    //得到开表中的最小F节点
    Point GetMinFPointByOpenList()
    {
        Point p = null;
        foreach (var value in open_List)
        {
            if (p == null || p.G+p.H > value.G+value.H)
            {
                p = value;
            }
        }

        return p;
    }

    /// <summary>
    /// 判断障碍物(0为通路,其他都是障碍)
    /// </summary>
    /// <param name="idx"></下标>
    /// <param name="map"></地图数据>
    /// <returns></true是障碍>
    bool IsHinder(int idx, byte[] map)
    {
        //越界判断
        if (idx >= map.Length)
        {
            return true;
        }

        return map[idx] != 0;

    }

    //判断点是否在开表中
    bool IsPointInOpenList(int x, int y)
    {
        foreach (var p in open_List)
        {
            if (p.X == x && p.Y == y)
            {
                return true;
            }
        }
        return false;
    }

    //判断点是否在闭表中
    bool IsPointInCloseList(int x, int y)
    {
        foreach (var p in close_List)
        {
            if (p.X == x && p.Y == y)
            {
                return true;
            }
        }
        return false;
    }

    //从开表中返回一个坐标数据
    Point GetPointByOpenList(int x, int y)
    {
        foreach (var p in open_List)
        {
            if (p.X == x && p.Y == y)
            {
                return p;
            }
        }
        return null;
    }

    //从闭表中返回一个坐标数据
    Point GetPointByCloseList(int x, int y)
    {
        foreach (var p in close_List)
        {
            if (p.X == x && p.Y == y)
            {
         
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
A*寻路算法是一种常用的路径规划算法,它在地图上寻找两个点之间的最短路径。在Unity中,我们可以使用以下步骤实现A*寻路算法: 1. 创建地图:我们需要创建一个网格地图,其中每个格子都代表着地图上的一个点。每个点都有一个坐标、可通过性和一些其他属性。 2. 创建节点类:我们需要创建一个节点类,用于保存每个点的信息。每个节点都有一个父节点、位置、代价和其他属性。 3. 创建Open和Close列表:我们需要创建两个列表,一个是Open列表,用于存储待搜索的节点,另一个是Close列表,用于存储已搜索过的节点。 4. 初始化起点和终点:我们需要初始化起点和终点,并将起点加入到Open列表中。 5. 搜索路径:我们需要重复以下步骤直到找到终点或者Open列表为空: a. 从Open列表中选取代价最小的节点作为当前节点。 b. 将当前节点从Open列表中删除,并将其加入到Close列表中。 c. 检查当前节点是否为终点,如果是则返回路径。 d. 遍历当前节点的相邻节点,计算它们的代价,并将它们加入到Open列表中。 6. 返回路径:如果找到了终点,则从终点开始沿着父节点一直往回走,直到回到起点。这样就得到了一条最短路径。 以下是示例代码: ```csharp using System.Collections; using System.Collections.Generic; using UnityEngine; public class AStar : MonoBehaviour { public LayerMask wallMask; public Vector2 gridSize; public float nodeRadius; Node[,] grid; float nodeDiameter; int gridSizeX, gridSizeY; void Start() { nodeDiameter = nodeRadius * 2; gridSizeX = Mathf.RoundToInt(gridSize.x / nodeDiameter); gridSizeY = Mathf.RoundToInt(gridSize.y / nodeDiameter); CreateGrid(); } void CreateGrid() { grid = new Node[gridSizeX, gridSizeY]; Vector3 worldBottomLeft = transform.position - Vector3.right * gridSize.x / 2 - Vector3.forward * gridSize.y / 2; for (int x = 0; x < gridSizeX; x++) { for (int y = 0; y < gridSizeY; y++) { Vector3 worldPoint = worldBottomLeft + Vector3.right * (x * nodeDiameter + nodeRadius) + Vector3.forward * (y * nodeDiameter + nodeRadius); bool walkable = !Physics.CheckSphere(worldPoint, nodeRadius, wallMask); grid[x, y] = new Node(walkable, worldPoint, x, y); } } } public List<Node> GetNeighbours(Node node) { List<Node> neighbours = 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 < gridSizeX && checkY >= 0 && checkY < gridSizeY) { neighbours.Add(grid[checkX, checkY]); } } } return neighbours; } public Node NodeFromWorldPoint(Vector3 worldPosition) { float percentX = (worldPosition.x + gridSize.x / 2) / gridSize.x; float percentY = (worldPosition.z + gridSize.y / 2) / gridSize.y; percentX = Mathf.Clamp01(percentX); percentY = Mathf.Clamp01(percentY); int x = Mathf.RoundToInt((gridSizeX - 1) * percentX); int y = Mathf.RoundToInt((gridSizeY - 1) * percentY); return grid[x, y]; } public List<Node> FindPath(Vector3 startPos, Vector3 targetPos) { Node startNode = NodeFromWorldPoint(startPos); Node targetNode = NodeFromWorldPoint(targetPos); 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 neighbour in GetNeighbours(currentNode)) { if (!neighbour.walkable || closedSet.Contains(neighbour)) { continue; } int newCostToNeighbour = currentNode.gCost + GetDistance(currentNode, neighbour); if (newCostToNeighbour < neighbour.gCost || !openSet.Contains(neighbour)) { neighbour.gCost = newCostToNeighbour; neighbour.hCost = GetDistance(neighbour, targetNode); neighbour.parent = currentNode; if (!openSet.Contains(neighbour)) { openSet.Add(neighbour); } } } } 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; } int GetDistance(Node nodeA, Node nodeB) { int distX = Mathf.Abs(nodeA.gridX - nodeB.gridX); int distY = Mathf.Abs(nodeA.gridY - nodeB.gridY); if (distX > distY) { return 14 * distY + 10 * (distX - distY); } return 14 * distX + 10 * (distY - distX); } public class Node { public bool walkable; public Vector3 worldPosition; public int gridX; public int gridY; public int gCost; public int hCost; public Node parent; public Node(bool _walkable, Vector3 _worldPos, int _gridX, int _gridY) { walkable = _walkable; worldPosition = _worldPos; gridX = _gridX; gridY = _gridY; } public int fCost { get { return gCost + hCost; } } } } ``` 在上面的代码中,我们首先创建了一个网格地图,并在其中创建了节点类。然后,我们实现了A*算法的核心部分,并将其用于在网格地图上搜索路径。在搜索结束后,我们返回了一条最短路径。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值