【Unity】【C#】A*寻路算法-学习心得

AI权益加码!Claude Code、Cursor等20+工具免费用! 购周边限时加赠Coding Plan Lite,畅享主流AI工具!学习进阶更高效! 阅读详情

昨天在阅读《U3d人工智能编程精粹》第三章的A*寻路算法的时候,由于书本只是粗略地用图片于伪代码展示了一遍A*寻路。,我便从网络中查找解读。经过翻阅多篇文章,似乎只有这位大大的博客文章(https://blog.csdn.net/yiyikela/article/details/46134339)写得较为详细,易于理解。

然后参考了(https://www.cnblogs.com/yangyxd/articles/5447889.html)[UNITY]A-star(A星)寻路 这篇文章,在Unity中编写了A*寻路。

以下整理一下本人学习A*寻路时,了解到的知识:

启发式搜索:

启发式搜索是通过利用问题所拥有的启发信息来指导搜索往最有希望的方向去,以达到减少搜索范围和降低目的复杂度的方法。

估价函数: 

用于评估节点代价的函数 :f(X)=g(x)+h(x)

g(x):初始节点到X节点的实际代价(起点到当前点的代价)

h(x):X节点到目标节点的预估代价(当前点到终点的代价)

f(x): 初始节点到X节点再到目标节点的代价估计(起点到终点的代价估计)

 

实现A*寻路的思路(个人见解):

《U3d人工智能编程精粹》里提及实现A*寻路有三种工作方式:

  • 创建基于单元的导航图
  • 创建可视点导航图
  • 创建导航网格

由于查阅资料以及书本提供的内容都是创建基于单元的导航图的工作方式来实现A*寻路,

我作为初学者也只能先写下通过创建基于单元的导航图实现方法的个人见解。(有机会可以自己摸索一下下面两种工作方式)

 

创建单元导航图:

创建基于单元的导航图,需要条件:

  • 构成导航图的点以及点的相关信息
  • 地图自身的相关信息

 点信息类:

      需要记录点在地图上的坐标 x , z 

      以及在世界坐标上的位置position

  public class AsNode
    {
        //点信息位置
        public Vector3 position;
        //点信息坐标 由于我采用三维坐标,所以采用 X Z方便自己读懂
        public int x,z;
        //构造点信息
        public AsNode(int x,int z)
        {
            this.x = x;
            this.z = z;
            this.position = new Vector3(x, 0, z);
        }
    }

 地图类:

     需要创建地图的宽高大小

     以及需要记录地图上的点信息----纵横相邻的点相距距离为1

public class MapGrid : MonoBehaviour {
    //地图大小(宽高)
    public const int mGridWidth = 10;
    public const int mGridHeigh = 10;
    //地图点信息
    public AsNode[,] mPointGrid = new AsNode[mGridWidth,mGridHeigh];

    //初始化地图上的点信息
    public void InitMapInfo()
    {
        //读取地图点的信息
        for (int i = 0; i < mGridHeigh; i++)
        {
            for (int j = 0; j < mGridWidth; j++)
            {
                mPointGrid[i, j] = new AsNode(i,j);
            }
        }
    }
    //绘制地图
    private void OnDrawGizmos()
    {
        for (int i = 0; i < mGridHeigh; i++)
        {
            for (int j = 0; j < mGridWidth; j++)
            {
               
                Gizmos.DrawWireCube(mPointGrid[i, j].position, Vector3.one);

            }
        }
    }
}

 

绘制导航图:

地图中还需要记录 初始节点 目标节点 障碍物节点:

由于点还区分是否为障碍物,所以为点添加属性

public class MapGrid : MonoBehaviour { 
    //起点
    public GameObject m_gameObject;
    //终点
    public GameObject target;
    //墙壁点
    public GameObject[] walls;
}

public class AsNode{
        public bool isWall;
        public AsNode(int x, int z,bool isWall)
        {
            this.x = x;
            this.z = z;
            this.isWall = isWall;
            this.position = new Vector3(x, 0, z);
        }
}

获取这些点信息需要重新改写我们的初始地图的方法:

创建基于单元的导航图类的代码:

public class MapGrid : MonoBehaviour {
    //地图大小(宽高)
    public const int mGridWidth = 10;
    public const int mGridHeigh = 10;    
    //地图上点的信息
    public class AsNode
    {
        public Vector3 position;
        //点信息坐标
        public int x,z;
        //地图点的状态
        public AsNode parent;
        public bool isWall;
        public AsNode(int x,int z)
        {
            this.x = x;
            this.z = z;
            this.position = new Vector3(x, 0, z);
        }

        public AsNode(int x, int z,bool isWall)
        {
            this.x = x;
            this.z = z;
            this.isWall = isWall;
            this.position = new Vector3(x, 0, z);
        }
    }
    //起点
    public GameObject m_gameObject;
    //终点
    public GameObject target;
    //墙壁点
    public GameObject[] walls;
    //地图点信息
    public AsNode[,] mPointGrid = new AsNode[mGridWidth,mGridHeigh];

    private void Start()
    {
        InitMapInfo();
    }


    public void InitMapInfo()
    {
        //读取地图点的信息
        for (int i = 0; i < mGridHeigh; i++)
        {
            for (int j = 0; j < mGridWidth; j++)
            {
                mPointGrid[i, j] = new AsNode(i,j);
                foreach(var wall in walls)
                { 
                    if (mPointGrid[i, j].position == wall.transform.position)
                        mPointGrid[i, j].isWall = true;
                }
            }
        }
    }

    //画地图
    private void OnDrawGizmos()
    {
        for (int i = 0; i < mGridHeigh; i++)
        {
            for (int j = 0; j < mGridWidth; j++)
            {
               
                Gizmos.DrawWireCube(mPointGrid[i, j].position, Vector3.one);

            }
        }
    }
}

 

此地图信息的起点、终点、障碍点,需要自行在U3D添加,然后挂载到脚本上(物体名字不需要关注,懒修改..)

效果图如下:

 

实现寻路算法:

寻路代码引用https://www.cnblogs.com/yangyxd/articles/5447889.html

实现寻路算法前,由于A*寻路是启发式搜索算法,通过估价函数来计算预期代价,来进行判断最终寻路路径。

并且寻路需要记录节点关系。

所以为点添加属性  f g h 和 parent;

以下为AsNode完整代码:

//地图上点的信息
public class AsNode
{
        public Vector3 position;
        //点信息坐标
        public int x,z;
        //地图点的状态
        public AsNode parent;
        public bool isWall;
        //估价函数
        public int g;//(起点到当前点)
        public int h;//(当前点到终点)
        public int f ;//f=g+h;

        public AsNode(int x,int z)
        {
            this.x = x;
            this.z = z;
            this.position = new Vector3(x, 0, z);
        }

        public AsNode(int x, int z,bool isWall)
        {
            this.x = x;
            this.z = z;
            this.isWall = isWall;
            this.position = new Vector3(x, 0, z);
        }
}

导航图创建完毕,开始思考寻路的实现。

既然是寻路,我们就需要吧已经走过的点,已经需要判断的点记录下来。

我们可以通过两个表来记录这两个信息:

  • openList:记录当前需要判断的点(考虑代价,是否能成为下一个路径点)
  • closedList:记录已经确定的点(已经走过,成为路径点)

①通过对当前点进行查找邻近点

      查找邻近点代码实现:

//取得周围的节点
    public List<AsNode> getNeibourhood(AsNode node)
    {
        List<AsNode> list = new List<AsNode>();
        for(int i = -1; i <= 1; i++)
        {
            for(int j = -1; j <= 1; j++)
            {
                if (i == 0 && j == 0)
                    continue;
                int x = node.x+i;
                int z = node.z+j;
                if (x < mGridWidth && x >= 0 && z < mGridHeigh && z >= 0)
                    list.Add(mPointGrid[x, z]); 
            }
        }
        return list;
    }

②将符合以下条件的点加入到openList中

  • 不是障碍物
  • 还没加入openList中

然后对openList中的邻近点进行估价计算(本案例采用了对角算法),F值小的成为下一个中间节点,并加入closedList中,并从openList中移除。

估价算法(对角算法):

黑线长度是通过三角形斜边公式计算出来的\sqrt{1^{2}+1^{2}}=\sqrt{2}\approx 1.414

以上述内容作为此寻路算法中的路径代价:

  • 水平,垂直移动代价为1
  • 斜向移动代价为1.4

通过判断两点之间的X差值,Z差值,若

  • X差值较大,则Y差值采用斜向移动,而X差值比Y差值多出来的部分使用水平/垂直移动

(由于斜向移动后的位置 相等于 分别进行一次水平移动和垂直移动)

(移动到相同位置,斜向移动代价为1.4,反之需要1+1=2)

(所以将差值较小的次数作为斜向移动次数计算)

所以预期代价为

14*(a.z-b.z)+10*(a.x-b.x)  或

14*(a.x-b.x)+10*(a.z-b.z)

实现代码:

public int getDistanceNodes(MapGrid.AsNode a,MapGrid.AsNode b)
{
        //采用对角算法 X(Y)差值较小的,采取对角
        //对角代价14
        //水平 垂直 代价10
        int cntX = Mathf.Abs(a.x - b.x);
        int cntZ = Mathf.Abs(a.z - b.z);
        if (cntX > cntZ)
            return 14 * cntZ + 10 * (cntX - cntZ);
        else
            return 14 * cntX + 10 * (cntZ - cntX);
}

获得新的路径点后,通过closeList的点,进行对路径进行更新。

直到查找到终点为止,否则一直进行邻居点查找,并比较估计代价的运算。

案例代码将获取的路径使用了点来打印出来。

寻路算法完整代码(参考博客):

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

public class FindPath : MonoBehaviour {
    public MapGrid grid;
	// Use this for initialization
	void Start () {
        grid = GetComponent<MapGrid>();
	}
	
	void Update () {
        FindingPath(grid.m_gameObject.transform.position, grid.target.transform.position);
	}

    //获取两个节点之间的距离
    public int getDistanceNodes(MapGrid.AsNode a,MapGrid.AsNode b)
    {
        //采用对角算法 X(Y)差值较小的,采取对角
        //对角代价14
        //水平 垂直 代价10
        int cntX = Mathf.Abs(a.x - b.x);
        int cntZ = Mathf.Abs(a.z - b.z);
        if (cntX > cntZ)
            return 14 * cntZ + 10 * (cntX - cntZ);
        else
            return 14 * cntX + 10 * (cntZ - cntX);
    }

    void FindingPath(Vector3 startPos, Vector3 endPos)
    {
        //通过坐标获取地图上的起点和终点
        MapGrid.AsNode startNode = grid.getItem(startPos);
        MapGrid.AsNode endNode = grid.getItem(endPos);
        //打开列表 存放邻近点
        List<MapGrid.AsNode> openList = new List<MapGrid.AsNode>();
        //关闭列表 存放选定的路径点
        List<MapGrid.AsNode> closedList = new List<MapGrid.AsNode>();
        openList.Add(startNode);
      
        while (openList.Count > 0)
        {
            MapGrid.AsNode curNode = openList[0];
            //(第一次运算)是用来将起点加入到关闭列表中
            //(后面的运算)通过判断还没到达终点,继续下面的执行过程获得新的打开列表(当前点的邻居点)
            for(int i = 0, max = openList.Count; i <max; i++)
            {
                //比较开启列表里的点 估价总值F 和点到终点的估价H
                //若列表中的点估价更低,替换为当前点
                if (openList[i].f <= curNode.f && openList[i].h < curNode.h)
                {
                    curNode = openList[i];
                }
            }
            //选择到点,然后加入到关闭列表中
            openList.Remove(curNode);
            closedList.Add(curNode);

            //直到找到终点为止
            if (curNode == endNode)
            {
                generatePath(startNode, endNode);
                return;
            }
         
            foreach (var item in grid.getNeibourhood(curNode))
            {
                //如果该点是障碍点,或者关闭列表已经有该点,跳过
                if (item.isWall || closedList.Contains(item))
                    continue;
                //可移动点,进行估价
                int newCost = curNode.g + getDistanceNodes(curNode, item);
                //如果距离更小,或者原来不在开始列表中
                if (newCost < item.g || !openList.Contains(item))
                {
                    //更新与开始节点的距离
                    item.g = newCost;
                    //更新与终点的距离
                    item.h = getDistanceNodes(item, endNode);
                    //更新父节点为当前选定的节点
                    item.parent = curNode;
                    //如果节点是新加入的,将它加入打开列表中
                    if (!openList.Contains(item))
                        openList.Add(item);
                }
            }
        }
        generatePath(startNode, null);
    }

    void generatePath(MapGrid.AsNode startNode,MapGrid.AsNode endNote)
    {
        List<MapGrid.AsNode> path = new List<MapGrid.AsNode>();
        if (endNote != null)
        {
            MapGrid.AsNode temp = endNote;
            while (temp != startNode)
            {
                path.Add(temp);
                temp = temp.parent;
            }
            //反转队列内容
            path.Reverse();
        }
        //更新路径
        grid.updatePath(path);
    }

}

地图信息映射完整代码(个人编写):

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

public class MapGrid : MonoBehaviour {
    //生成路径点预载体
    public GameObject Node;
    //地图大小(宽高)
    public const int mGridWidth = 10;
    public const int mGridHeigh = 10;
    //地图上点的信息
    public class AsNode
    {
        public Vector3 position;
        //点信息坐标
        public int x,z;
        //地图点的状态
        public AsNode parent;
        public bool isWall;
        //估价函数
        public int g;//(起点到当前点)
        public int h;//(当前点到终点)
        public int f ;//f=g+h;

        public AsNode(int x,int z)
        {
            this.x = x;
            this.z = z;
            this.position = new Vector3(x, 0, z);
        }
        public AsNode(int x, int z,bool isWall)
        {
            this.x = x;
            this.z = z;
            this.isWall = isWall;
            this.position = new Vector3(x, 0, z);
        }
    }

    //起点
    public GameObject m_gameObject;
    //终点
    public GameObject target;
    //墙壁点
    public GameObject[] walls;
    //地图点信息
    public AsNode[,] mPointGrid = new AsNode[mGridWidth,mGridHeigh];
    //路径目标
    private List<GameObject> pathObj = new List<GameObject>();
  
    private void Start()
    {
        InitMapInfo();
    }

    public void InitMapInfo()
    {
        //读取地图点的信息
        for (int i = 0; i < mGridHeigh; i++)
        {
            for (int j = 0; j < mGridWidth; j++)
            {
                mPointGrid[i, j] = new AsNode(i,j);
                foreach(var wall in walls)
                {
                    if (mPointGrid[i, j].position == wall.transform.position)
                        mPointGrid[i, j].isWall = true;
                }
            }
        }
    }

    //画地图
    private void OnDrawGizmos()
    {
        for (int i = 0; i < mGridHeigh; i++)
            for (int j = 0; j < mGridWidth; j++)
                Gizmos.DrawWireCube(mPointGrid[i, j].position, Vector3.one);
    }

    //取得周围的节点
    public List<AsNode> getNeibourhood(AsNode node)
    {
        List<AsNode> list = new List<AsNode>();
        for(int i = -1; i <= 1; i++)
        {
            for(int j = -1; j <= 1; j++)
            {
                if (i == 0 && j == 0)
                    continue;
                int x = node.x+i;
                int z = node.z+j;
                if (x < mGridWidth && x >= 0 && z < mGridHeigh && z >= 0)
                    list.Add(mPointGrid[x, z]); 
            }
        }
        return list;
    }

    //更新路径
    public void updatePath(List<AsNode> lines)
    {
        int curListSize = pathObj.Count;
        for(int i = 0, max = lines.Count; i < max; i++)
        {
            if (i < curListSize)
            {
                pathObj[i].transform.position = lines[i].position;
                pathObj[i].SetActive(true);
            }
            else
            {
                GameObject obj = GameObject.Instantiate(Node, lines[i].position, Quaternion.identity);
                pathObj.Add(obj);
            }
        }
    }
    //通过坐标找地图上的点
    public AsNode getItem(Vector3 pos)
    {
        int x = Mathf.RoundToInt(pos.x);
        int z = Mathf.RoundToInt(pos.z);
        return mPointGrid[x, z];
    }
}

 

A*寻路实现效果图:

【白点为起点(初始节点)】

【绿点为阻碍点(不可移动节点)】

【红点为终点(目标节点)】

【蓝点为路径点(中间节点X)】

Unity A星(A Star/A*寻路算法 演示: 我们知道Unity中的Navigation只能实现3D场景的寻路,不能实现2D的寻路,常见的寻路算法有很多种,其中A星是项目中最常用的寻路方法。在项目中用到了A星,就简单总结一下吧。 原理: 最通俗的原理就是寻找周围的。选出一个到终最近,再从选出的为起寻找下一个,直到到达目标。 实现: 如何选出最近呢,我们就会利用曼哈顿街区算法公式寻找下一个。 如下图:我们以黄色为起,黄色的周围有八个可以移动的,移动的距离对角移动为1.4,直线移动为1。 .. 阅读详情

相关推荐

Unity寻路A星算法

A*寻路中,从一个节到另一个相邻节的移动成本通常不是简单的单位距离,而是可以根据地形、障碍物、角色能力等因素来定制。总之,在A*寻路算法中,移动成本是一个灵活的概念,需要根据具体的游戏环境或实际问题需求来设计和实施。否则,将其相邻的未探索过的节加入到优先级队列中。对于新加入优先级队列的相邻节,计算其G值(从起到达该节的实际代价)、H值(启发式估计值,即到目标节的预计代价),然后根据公式。在实现过程中,当计算相邻节的F值(总成本)时,G值会包括前一节到当前节的实际移动成本,即。

qqrrjj2011的博客 2790

unityA*寻路

二、 思路解析 我们先来了解一下A*寻路的思路: 1.每个块需要一个数据类,这个类中要存的数据有: 每个移动方块都有三个值F=G+H、G(代表起到当前的距离)H(当前到终的距离)。并且每个移动方块都会存储自己上一个块(Parent) 2.首先 创建一个开放列表(OpenList:存放已经找到并计算好FGH值的周围块)和一个关闭列表(closeList:不可移动的块,如起、障碍物和已经走过的块) 3.将起放入开放列表(openList)中,只要开放列表(openList)中存在可移动

qq_42345116的博客 3312

Unity中实现Astar寻路算法

在游戏中,从一到另一的操作有时需要游戏系统自动完成,在一些带有rpg元素的游戏中,敌人在发现玩家位置后会自动向玩家的位置移动。这些移动的路线是如何自动确定的?本文将介绍寻路算法中的A*算法,并在unity中用C#脚本来实现寻路功能。

Meytones的博客 2704

unity 游戏中的寻路与导航系统(5种寻路算法详解)

1.了解游戏中常见的驯鹿方式 2.寻路方案选择 3.NavMesh 寻路 4.任务目标追踪 5.常见的寻路方式-建模方式 寻路建模 Grid WayPoint NavMesh

lfanyize的博客 2万+

Unity | A*寻路算法

A*(A-Star)简介在游戏开发的过程中,不免需要涉及到怪物AI的寻路或让玩家自动导航到目标位置,当在没有障碍的场景中,直接让怪物/玩家向目标移动即可,但在有障碍物的场景中(如迷宫,房间,围墙等等),寻路算法就变得尤为重要。A*是目前主流的寻路算法之一,它的作用就是寻找开始与目标之间,避开障碍的最短路径。

持续学习! 4066

Unity学习笔记】A*寻路算法

而不是类似Dijkstra算法,每次遍历相邻结时尽管下一个结可能出现权值过大的情况,但是我们不能确保它不是全局最优的,因此我们依然要把它加入到遍历路径中。贪心算法适用于路径带有不同权值的时候,遍历时我们优先遍历相邻结中权值较小者,这样做的好处是如果找到了路径,那么我们的路径一定是部分最短的(相邻结永远是最短的,虽然不一定是全局最短,但是相对来说不会是最差的)依次类推,按照表格上的路径,在第二轮发现v4达到不了v3,因此我们放弃这条路径,再次回到第二轮,选择除了这条路径以外最短的,也就是。

milu_ELK的博客 2166

游戏开发实战:A*算法Unity中实现NPC智能寻路(附C#代码)

本文详细介绍了A*算法Unity游戏开发中实现NPC智能寻路的核心步骤与优化策略。通过构建网格系统、实现算法核心循环,并结合C#代码示例,帮助开发者掌握高效寻路模块的创建。文章还探讨了性能优化、动态障碍处理及分层寻路等高级话题,为RPG、策略等类型游戏提供实战解决方案。

tech5的博客 1110

unity中实现A*算法的一些问题

声明:这不是A*算法教程!!!这不是A*算法教程!!! 前一段时间,我参与了某游戏项目,负责AI部分。项目提出这样的要求: 游戏场景为一个巨大的立方体。立方体的每一个面都是一个迷宫,而上面都有若干怪物。如果玩家到达立方体的某一个侧面上,该侧面上的怪物会进行寻路,追踪玩家。 该项目采用unity3D游戏引擎,但是我发现unity自带NavMesh组件似乎不能实现一个场景建立多个Nav

就是这样一个博客 3540

Unity实现可视化A*寻路

Unity实现可视化A*寻路 效果图

weixin_43455008的博客 1190

UnityA*寻路算法

文章目录一、前言二、完整代码 一、前言 本文为a*寻路算法的简单实现,在此记录。 本文对应项目:GitHub 说明: 1、Unity版本为-2019.4.27 2、文章中的Tile可替换为Point 参考文章:A*算法C#实现 二、完整代码 using System.Collections; using System.Collections.Generic; using UnityEngine; public class AStar { private AStar() { } publ

HG2131的博客 4264

Unity】基于A*算法的简单寻路代码实现

using System.Collections; using System.Collections.Generic; using UnityEngine; public class AStarAlgorithm { const int XLength = 10; const int YLength = 10; public AStarPoint[,] pointGrid = new AStarPoint[XLength,YLength]; public Stack..

Currybeefer的博客 732

unityA*算法的实现

算法介绍 A*(念做:A Star)算法是一种很常用的路径查找和图形遍历算法。它有较好的性能和准确度。本文在讲解算法的同时也会提供Python语言的代码实现,并会借助matplotlib库动态的展示算法的运算过程。 A*算法最初发表于1968年,由Stanford研究院的Peter Hart, Nils Nilsson以及Bertram Raphael发表。它可以被认为是Dijkstra算法的扩展。 由于借助启发函数的引导,A*算法通常拥有更好的性能。 A*算法通过下面这个函数来计算每个节的优先级。 其中

qq_41055920的博客 2672

C#实现A*寻路算法:从原理到Unity游戏集成实战

在游戏开发和人工智能领域,路径规划是核心基础技术之一,它决定了角色如何在复杂环境中智能移动。其基本原理是通过图搜索算法,在节网络中寻找从起到终的最优路径,技术价值在于平衡搜索效率与路径质量。A*算法作为经典启发式搜索算法,通过引入预估成本(启发函数)显著提升搜索效率,广泛应用于游戏NPC移动、机器人导航、战略游戏单位调度等场景。本文聚焦于A*算法在游戏开发中的工程实践,详细拆解其核心三要素(G、H、F值)与运行流程,并提供完整的C#实现方案,重解决游戏开发中常见的NPC智能移动与障碍物规避问题,通过

weixin_30268921的博客 564

Unity2D当中的A*寻路算法

本文详细介绍了A寻路算法的实现原理和代码实现。A算法是深度优先搜索的优化版本,通过评估函数(当前路径距离+预估终距离)优先搜索最优路径。文章首先阐述了算法原理,包括开放列表和关闭列表的使用、路径评估方法等。然后给出了完整的C#实现代码,包含IPathData接口、PathNode类以及核心寻路逻辑。实现中采用曼哈顿距离作为启发函数,并提供了两种寻路方法:一种考虑可通行区域限制,另一种不考虑。最后还介绍了路径回溯和距离计算等辅助方法。整个实现约150行代码,适用于Unity游戏开发中的寻路需求。

qq_39332021的博客 1028

算法实战】手把手带你用 C# 实现 A* (A-Star) 寻路算法

本文详细介绍了A寻路算法在游戏开发中的应用。A算法结合了Dijkstra算法的最短路径保证和贪婪算法的效率优势,通过F=G+H公式评估节价值,其中G为实际移动成本,H为启发式预估成本。文章讲解了曼哈顿距离和欧几里得距离两种常用启发函数,并给出算法流程:维护开启列表和关闭列表,循环查找F值最小的节,直至找到终。最后提供了C#实现代码,使用PriorityQueue优化性能,包含节定义、启发函数计算和路径搜索的核心逻辑。该算法是游戏自动寻路系统的关键技术,兼顾路径最优性和计算效率。

qq_42555291的博客 1515

UnityA*寻路(AStar,A星)的优化,二叉堆,双向队列,哈希表

对A星寻路的进一步优化,二叉堆,哈希表,双向队列

XueZhiXia_的博客 3246

A星寻路的实现,基于Unity C#

算法简介 A*简单高效,可用于许多寻路算法中。 在这里我们共实现Node类,PriorityQueue类,NodeManager类和AStar类。 在Node类中,我们管理每个地图块的信息,包括是否为障碍、估值等。 PriorityQueue类用于储存处理完毕的和待处理的节。 NodeManager类用来管理我们的Node类,在这里我们使用二维数组来管理。 AStar类则是我们的算法实现类。 步...

qq_38015139的博客 867

Unity A*寻路算法实战:从原理到动态演示的完整实现

本文详细解析了UnityA*寻路算法的实现原理与实战应用。从算法核心概念(G值、H值、F值)到Unity中的完整实现步骤,包括场景搭建、动态演示技巧及性能优化策略。特别介绍了数据结构优化、分层寻路策略等进阶技巧,帮助开发者高效解决游戏中的路径规划问题。

weixin_29281915的博客 683

Unity游戏开发AI-A*寻路算法

Unity3d利用A*寻路算法实现寻路模拟 https://blog.csdn.net/qq_33747722/article/details/78436919 【Unity】【C#A*寻路算法-学习心得 https://blog.csdn.net/Terrell21/article/details/82584634 自己实现效果 设置point using System.Coll...

qq_35422344的博客 857
上一篇: 【Unity】【C#】《U3d人工智能编程精粹》学习心得--------操纵行为--路径跟随
下一篇: 【Unity】【C#】《U3d人工智能编程精粹》学习心得--------AI角色的感知方式(Trigger,Sensor,TriggerSystemManager)基类实现解读
Terrell21
博客等级 码龄9年 39粉丝 33原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值