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

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

昨天在阅读《U3d人工智能编程精粹》第三章的A*寻路算法的时候,由于书本只是粗略地用图片于伪代码展示了一遍A*寻路。,我便从网络中查找解读。经过翻阅多篇文章,似乎只有这位大大的博客文章(https://blog.youkuaiyun.com/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*寻路(AStar,A星)的优化,二叉堆,双向队列,哈希表 对A星寻路的进一步优化,二叉堆,哈希表,双向队列 阅读详情

相关推荐

Unity 算法 之 A星(A Star/A*)寻路算法实现和封装,并带动态演示Demo

Unity 算法 之 A星(A Star/A*)寻路的算法法实现和封装,并带动态演示Demo 目录 Unity 算法 之 A星(A Star/A*)寻路的算法法实现和封装,并带动态演示Demo 一、简单介绍 二、 A星(A Star/A*)寻路算法相关知识 1、什么是A星(A Star/A*)寻路算法 2、寻路:寻找最短路径并避开障碍物 3、几个重要的概念 4、寻路结束的条件...

仙魁XAN 1万+

C# A*算法

A*算法是一种广泛使用的路径搜索算法,通常用于寻找在给定地图或图形中,起点到目标点之间的最短路径。它是一种基于贪心策略的启发式搜索算法,可以在大多数情况下找到最短路径。

無限進步的全棧遊戲開發的博客 2607

在Unity中实现Astar寻路算法

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

Meytones的博客 2711

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

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

lfanyize的博客 2万+

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

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

就是这样一个博客 3543

Unity实现可视化A*寻路

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

weixin_43455008的博客 1193

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

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

milu_ELK的博客 2172

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

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

weixin_30268921的博客 569

Unity寻路A星算法

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

qqrrjj2011的博客 2800

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

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

qq_38015139的博客 872

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

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

weixin_29281915的博客 689

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

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

tech5的博客 1118

目标检测数据集 第059期-基于yolo标注格式的水果李子检测数据集(含免费分享)

李子作为中国三大水果之一,种植历史超 3000 年,在市场中占据重要地位。传统李子种植、施肥、采摘依赖大量人力,存在资源浪费、产量估算不准、采摘时机难把控等问题。此前,农业领域缺乏针对 “未成熟李子” 的专用数据集,现有水果检测数据集多聚焦于成熟果实(如苹果、柑橘),且未覆盖李子种植的复杂自然场景。在使用该数据集进行学术研究时,应遵守相关的学术规范,引用该数据集的来源,尊重数据集创作者的劳动成果。,用于训练改进型模型,解决李子精准检测的核心痛点。

深度学习算法工程师,专注于前沿算法研究与实战应用。在这里,我将分享深度学习领域的实战经验、优质数据集资源以及最新论文解读与精度分析,旨在与广大技术爱好者共同探索人工智能的奥秘,助力技术成长与创新。 771

【Unity】A*寻路算法

文章目录一、前言二、完整代码 一、前言 本文为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的博客 4267

k8s集群部署私有镜像仓库

本文介绍了在Kubernetes集群中部署私有镜像仓库的完整方案。使用registry:2镜像创建Deployment,通过NodePort(30500)暴露服务,并采用hostPath(/data/registry)实现数据持久化。部署过程包括节点标记、YAML配置、资源创建及验证步骤,同时提供了Docker和Containerd两种环境下的详细使用方法,包括配置不信任私有仓库、镜像推送/拉取操作指南。该方案特别适合开发测试环境,为团队提供便捷的本地镜像管理能力。

weixin_42728286的博客 892

使用在UE5中使用AirSim插件Eigen库头文件引用报错,出现报错的解决方式

如图所示,用红线圈出的两条头文件引用会报错,提示无法找到他们,但是可以发现的是,他们的路径书写是没有问题的。在终端中运行时候,会出现如下的报错。

GFCLJY的博客 1006

【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的博客 736

超强干货之---Python-数据爬取(爬虫)

定义: 深度优先搜索是一种遍历或搜索树或图的算法,从起始节点开始,一直沿着一个分支走到底,再回溯到上一个节点继续搜索下一个分支,直到遍历完所有节点。特点递归:通常用递归实现,或者使用栈来模拟递归过程。内存占用低:在有大量分支的情况下,内存占用比广度优先搜索低。适合目标较深的情况:如果目标节点距离起始节点较深,DFS能更快找到目标。适用场景需要遍历所有节点的情况,如生成树、迷宫搜索。目标节点较深,且分支较多时。在大规模数据爬取时,选择合适的存储方式取决于数据的规模、结构和访问需求。

房东的猫的博客 5万+

unity中A*算法的实现

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

qq_41055920的博客 2680

DSP2837X CLA开发实战教程

摘要: 本文详细解析TI C2000 DSP中CLA协处理器的开发流程,以TMS320F28377D的cla_divide案例为例,展示浮点除法验证的实现方法。从基础配置(消息RAM管理、任务触发)到高级调试(ePWM计时、断点设置),涵盖全流程开发要点。重点分析CLA编程约束(禁用标准库、数学优化)、多任务调度及常见问题解决方案(如死锁、数据同步)。提供FPGA协同加速、电机控制等扩展方向,并推荐官方例程与硬件平台(如创龙TL2837xF-EVM)。开发时需注意.cla文件语法支持及调试技巧,以充分发挥C

6758

AI测试:手把手教你用AI做桌面自动化「喂饭教程」

本文介绍了基于MCP协议的DesktopCommanderMCP自动化工具,通过自然语言指令实现桌面操作。系统采用客户端-服务器架构,支持应用程序管理、文件操作、屏幕控制等功能。详细说明了环境搭建步骤,包括Python和Node.js依赖安装、API密钥配置及MCP服务部署。通过实战案例展示了文件整理、批量截图等典型应用场景,并分享了任务描述优化、权限控制等最佳实践。该方案能显著提升重复性桌面操作的效率,让AI成为智能办公助手。

blues_C的博客 851

Unity2D当中的A*寻路算法

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

qq_39332021的博客 1033

实战交易策略 篇二十二:情绪流龙头交易策略

在股票市场中,机构主导趋势,游资驱动热点,散户易被情绪裹挟,形成“金字塔”式生态链,并存在情绪传递、强者恒强、物极必反的规律特点。股市是资金驱动的情绪博弈场,价格波动由群体心理、资金博弈和预期差共同驱动,核心是资本逐利性与人性贪婪恐惧的交织,兼具资源配置、财富再分配与风险定价功能。涨停加速与逃逸缺口(主升强化)凹字板/平台突破(趋势延续)天量弱转强(分歧买点)不参与首波(二波策略)情绪周期(道术合一)主线思维(聚焦核心)开盘抢筹(竞价博弈)一字助攻(情绪强化)分批进出(滚动操作)

生活在别处 1486

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

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

qq_42555291的博客 1550

零基础做完YOLOv8船只检测系统:HRSC2016数据集 + 完整UI,稳过答辩

亲爱的同学,通过这篇教程,你已经掌握了“基于YOLOv8的HRSC2016微小船只检测系统”从数据集处理、模型训练到Tkinter界面开发的全流程。这个课题既贴合“海事智能化”的产业战略,又涵盖了“目标检测、深度学习、界面开发”等多个毕设评分点,非常适合作为计算机或海事工程专业的毕业设计。在实践中,你可能会遇到“海面背景复杂导致船只漏检”“微小船只识别精度不足”“UI与模型推理同步卡顿”等挑战——别担心,这些都是技术成长的必经之路。

FJN110的博客 107

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

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

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

qq_35422344的博客 860

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

上一篇: 【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、付费专栏及课程。

余额充值