Unity AStar寻路代码模板

下面是一个基本的Unity AStar寻路代码模板:

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

public class AStar : MonoBehaviour
{
    // 节点类
    public class Node
    {
        public int x; // x坐标
        public int y; // y坐标
        public bool walkable; // 是否可走
        public Node parent; // 父节点
        public int gCost; // 从起点到该节点的成本
        public int hCost; // 从该节点到终点的估算成本
        public int fCost // fCost = gCost + hCost

        public Node(int x, int y, bool walkable)
        {
            this.x = x;
            this.y = y;
            this.walkable = walkable;
        }

        public int GetFCost()
        {
            return gCost + hCost;
        }
    }

    public Node[,] grid; // 地图
    public int gridSizeX; // 地图宽度
    public int gridSizeY; // 地图高度
    public Transform start; // 起点
    public Transform end; // 终点

    private List<Node> openList; // 开放列表
    private List<Node> closedList; // 封闭列表

    // 启动寻路
    public void StartPathfinding()
    {
        openList = new List<Node>();
        closedList = new List<Node>();

        Node startNode = GetNodeFromPosition(start.position);
        Node endNode = GetNodeFromPosition(end.position);

        openList.Add(startNode);

        while (openList.Count > 0)
        {
            Node currentNode = GetLowestFCostNode(openList);

            if (currentNode == endNode)
            {
                // 找到终点,生成路径
                List<Node> path = GeneratePath(startNode, endNode);
                // TODO: 处理路径
                return;
            }

            openList.Remove(currentNode);
            closedList.Add(currentNode);

            foreach (Node neighborNode in GetNeighborNodes(currentNode))
            {
                if (!neighborNode.walkable || closedList.Contains(neighborNode))
                {
                    // 忽略不可走节点或已在封闭列表中的节点
                    continue;
                }

                int tentativeGCost = currentNode.gCost + GetDistance(currentNode, neighborNode);

                if (tentativeGCost < neighborNode.gCost || !openList.Contains(neighborNode))
                {
                    neighborNode.parent = currentNode;
                    neighborNode.gCost = tentativeGCost;
                    neighborNode.hCost = GetDistance(neighborNode, endNode);
                    if (!openList.Contains(neighborNode))
                    {
                        openList.Add(neighborNode);
                    }
                }
            }
        }

        // 无法到达终点
        // TODO: 处理无法到达终点的情况
    }

    // 根据坐标获取节点
    private Node GetNode(int x, int y)
    {
        if (x >= 0 && x < gridSizeX && y >= 0 && y < gridSizeY)
        {
            return grid[x, y];
        }
        else
        {
            return null;
        }
    }

    // 根据位置获取节点
    private Node GetNodeFromPosition(Vector3 position)
    {
        int x = Mathf.RoundToInt(position.x);
        int y = Mathf.RoundToInt(position.z);
        return GetNode(x, y);
    }

    // 获取相邻节点
    private List<Node> GetNeighborNodes(Node node)
    {
        List<Node> neighborNodes = 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.x + x;
                int checkY = node.y + y;

                Node neighborNode = GetNode(checkX, checkY);

                if (neighborNode != null)
                {
                    neighborNodes.Add(neighborNode);
                }
            }
        }

        return neighborNodes;
    }

    // 获取两个节点之间的距离
    private int GetDistance(Node nodeA, Node nodeB)
    {
        int distanceX = Mathf.Abs(nodeA.x - nodeB.x);
        int distanceY = Mathf.Abs(nodeA.y - nodeB.y);

        if (distanceX > distanceY)
        {
            return 14 * distanceY + 10 * (distanceX - distanceY);
        }
        else
        {
            return 14 * distanceX + 10 * (distanceY - distanceX);
        }
    }

    // 获取开放列表中fCost最小的节点
    private Node GetLowestFCostNode(List<Node> nodeList)
    {
        Node lowestFCostNode = nodeList[0];

        for (int i = 1; i < nodeList.Count; i++)
        {
            if (nodeList[i].fCost < lowestFCostNode.fCost)
            {
                lowestFCostNode = nodeList[i];
            }
        }

        return lowestFCostNode;
    }

    // 生成路径
    private List<Node> GeneratePath(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;
    }
}

使用时,需要在场景中创建一个空物体,将上面的代码作为其组件,并设置相应的参数,如地图大小、起点和终点位置等。然后,调用`StartPathfinding`方法启动寻路即可。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值