A*寻路

Unity3D 高效A*寻路 Unity Asset Store URL: http://u3d.as/1ud5 随着手机游戏不断发展, 我们需要在手机做更多的表现, 但手机的性能是有限的。每个重要模块都应尽可能地有很好的性能来提升整个表现效果。寻路算法中, 普通的a*在比较大的地图时, 消耗性能也是具大, 因此, 我把a*作了很好的改良。这已作为简单的工具类使用即可, 插件中包括阻挡数据的生成工具, 寻路算法的使用Demo... 阅读详情

在很多游戏中我们需要让角色用最快的速度到达目标地点,于是我们需要找到一条最短的路径或是比较短的路径,于是出现很多寻路算法,在此介绍较为高效的A* 算法。

原理:把一个2D或者3D的场景解析成由很多方块或者方体组成,给每个方块赋予坐标值,则可以出现起始点的坐标值。        

依托公式F=H+G; 靠谱指数=预计耗费+移动到当前已经耗费

关键集合:openList<point> 用来储存将要判断F值的点,closeList<point>用来储蓄已经判断过F值得点;

实现思路:

  1. 自定义起始点和终点(point start = map[2, 3]; point end = map[6, 3];)  
  2. 新建openList<point>往里添加起始点。
  3. 用while判断如果openlist>0; 寻找openlist里最小F的点,把这点移除openlist,添加closelist. 
  4. 新建sorroundList用来储存最小点周围的点;
  5. 过滤是否在closeList
  6. 遍历这些点是否在openList里面,如果是则判断周围的点和openlist里的点的G值,因为H知同一点一样(新建判断G值函数);如果当前点G值比opnelist的这一点G值小,则把这一点的父点改为最小F的点;
  7. 如果不在openlist则添加
  8. 再一次判断openlist里最小F的点,重复4.5.6.7
  9. 知道结束点在openlist里面打破循环;


point类

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

public class point  {

    public point Parent { get; set; }
    public float F { get; set; }
    public float G { get; set; }
    public float H { get; set; }

    public int X { get; set; }
    public int Y { get; set; }
    public bool IsWall { get; set; }                //

    public point(int x,int y,point parent=null)
    {
        this.X = x;
        this.Y = y;
        this.Parent = parent;
        IsWall = false;
    }
	
    public void UpDateParent(point parent,float g)
    {
        this.Parent = parent;
        this.G = g;
        this.F = G + H;
    }

}

逻辑类

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

public class AStart : MonoBehaviour {                           //在开集合中找最小值,创建这一点的周围集合
                                                                //这个周围集合是否有点在开集合,有就比较,替换
    public float width = 8;
    public float height = 6;
    private point[,] map = new point[8, 6];

	// Use this for initialization
	void Start () {
        InitMap();
        point start = map[2, 3];
        point end = map[6, 3];
        FindPath(start,end);
        ShowPath(start,end);

        //List<point> li = GetSurroundPoint(map[3, 3]);
        //foreach (point p in li)
        //{
        //    Debug.Log(p.X+"-"+p.Y);
            
        //}

		
	}
    public void InitMap()                                   //初始化
    {
        for (int i=0;i<8;i++)
        {
            for (int j=0;j<6;j++)
            {
                map[i, j] = new point(i,j);
            }
        }
        map[4, 2].IsWall = true;
        map[4, 3].IsWall = true;
        map[4, 4].IsWall = true;


    }

    public void ShowPath(point start,point end)
    {
        point temp = end;
        while (true)
        {
            Debug.Log(temp.X+","+temp.Y);
            temp = temp.Parent;
            if (temp.Parent==null)
            {
                Debug.Log(temp.X + "," + temp.Y);
                break;
            }
        }

    }

    public void FindPath(point start,point end)             //寻找路径(起点,终点)
    {
        List<point> openList = new List<point>();
        List<point> closeList = new List<point>();
        openList.Add(start);                                //
        while (openList.Count>0)
        {
            point point1 = FindMinF(openList);
            openList.Remove(point1);
            closeList.Add(point1);
            List<point> surroundPointd = GetSurroundPoint(point1);                  //获得附近的点
            PointsFilter(surroundPointd,closeList);                                 //过滤这些点是否在闭集合

            foreach (point surroundPoint in surroundPointd)
            {
                if (openList.IndexOf(surroundPoint)>-1)                             //周围的点是否在开集合中出现过
                {
                    float nowG = CalcG(surroundPoint,point1);                       //当前G值==当前到父类距离+父类G
                    if (nowG < surroundPoint.G)                                     //原本在开集合这点的G值
                    {
                        surroundPoint.UpDateParent(point1,nowG);
                    }
                }
                else                                                                //如果开集合没有则添加,并赋值
                {
                    surroundPoint.Parent = point1;
                    CalcF(surroundPoint,end);                                       //
                    openList.Add(surroundPoint);
                }
            }
            if (openList.IndexOf(end)>-1)
            {
                break;
            }

        }
    }

    public void PointsFilter(List<point> surroundPointd,List<point> closeList)      //过滤周围在闭集合的点
    {
        foreach (point p in closeList)
        {
            if (surroundPointd.IndexOf(p)>-1)                                       //闭集合存在则移除
            {
                surroundPointd.Remove(p);
            }
        }
    }

    public List<point> GetSurroundPoint(point point)        //获得周围的点
    {
        point up = null, down = null, left = null, right = null;
        point upLeft = null, upRight = null, downLeft = null, downRight = null;
        List<point> list = new List<point>();


        //先判断上下左右是否为边界,在判断是否为为空,不为墙
        if (point.Y<(6-1))
        {
            up = map[point.X, point.Y + 1];
            if (up!=null&&up.IsWall==false)
            {
                list.Add(up);
            }
        }
        if (point.Y > (0))
        {
            down = map[point.X, point.Y - 1];
            if (down != null && down.IsWall == false)
            {
                list.Add(down);
            }
        }
        if (point.X < (8 - 1))
        {
            right = map[point.X+1, point.Y];
            if (right != null && right.IsWall == false)
            {
                list.Add(right);
            }
        }
        if (point.X > (0))
        {
            left = map[point.X-1, point.Y];
            if (left != null && left.IsWall == false)
            {
                list.Add(left);
            }
        }


        /////左上存在时,左和上必须不为空,不为墙,自己也不能为空不能为墙
        if (up!=null&&left!=null)
        {
            upLeft = map[point.X - 1, point.Y + 1];
            if (up.IsWall==false&&left.IsWall==false&&upLeft!=null&&upLeft.IsWall==false)
            {
                list.Add(upLeft);
            }
        }
        if (up != null && right != null)
        {
            upRight = map[point.X + 1, point.Y + 1];
            if (up.IsWall == false && right.IsWall == false && upRight != null && upRight.IsWall == false)
            {
                list.Add(upRight);
            }
        }
        if (down != null && left != null)
        {
            downLeft = map[point.X - 1, point.Y - 1];
            if (down.IsWall == false && left.IsWall == false && downLeft != null && downLeft.IsWall == false)
            {
                list.Add(downLeft);
            }
        }
        if (down != null && right != null)
        {
            downRight = map[point.X + 1, point.Y - 1];
            if (down.IsWall == false && right.IsWall == false && downRight != null && downRight.IsWall == false)
            {
                list.Add(downRight);
            }
        }

        return list;
    }

    private point FindMinF(List<point> openList)            //寻找最小的的F
    {
        float f = float.MaxValue;
        point temp = null;
        foreach (point p in openList)
        {
            if (p.F<f)
            {
                temp = p;
                f = p.F;
            }
        }
        return temp;
    }

    private void CalcF(point now,point end)                     //当前点和终点,给F,G,H赋值
    {
        //F=G+H
        float h = Mathf.Abs(end.X - now.X) + Mathf.Abs(end.Y-now.Y);
        float g = 0;
        if (now.Parent==null)
        {
            g = 0;
        }
        else
        {
            g = Vector2.Distance(new Vector2(now.X, now.Y), new Vector2(now.Parent.X, now.Parent.Y))+now.Parent.G;
        }
        float f = g + h;
        now.F = f;
        now.G = g;
        now.H = h;
    }

    private float CalcG(point now,point parent)
    {
        return Vector2.Distance(new Vector2(now.X, now.Y), new Vector2(parent.X, parent.Y))+parent.G;
    }

    // Update is called once per frame
    void Update () {
		
	}
}


A* Pathfinding Project (Unity A*寻路插件) 使用教程 下面是动态图,借助 A* 插件,编写很少的代码就可以做到寻路。 1、创建场景 在场景中添加一些Cube 作为障碍物 Obstacles,添加一个 Capsule 作为Player,然后添加一个Plane 作为地面,再添加一个Plane,作为斜坡测试。 在创建一个GameObject,改名为 A* ,添加A Star Path ( 阅读详情

相关推荐

A*迷宫寻路

特点:计算简单快速,在迷宫寻路中能提供相对合理的估计,但在某些情况下可能会导致搜索路径不是最优(如存在斜向移动成本与水平 / 垂直移动成本相同时)。

J1481852914的博客 1600

A*算法简介

A*算法是一种启发式的搜索算法, A*算法在某种程度上和广度优先搜索( BFS)、 深度优先搜索( DFS) 类似, 都是按照一定的原则确定如何展开搜索的节点树状结构。 A*可以认为是一种基于“ 优点” 的搜索算法。搜索区域(The Search Area):我们假设某人要从 A 点移动到 B 点, 但是这两点之间被一堵墙隔开。 如图 1 ,绿色是 A , 红色是 B , 中间蓝色是墙。你应该注意到了, 我们把要搜寻的区域划分成了正方形的格子。 这是寻路的第一步, 简化搜索区域。 这个特殊的方法把我们的搜索

ponnyao学习笔记 3278

A*算法实现

机器人全局路径规划,用于移动机器人导航,设定目标点到起始点的最优路径规划

A*算法原理简析

A算法是一种启发式的搜索算法,它是基于深度优先算法和广度优先算法的一种融合算法,按照一定规则确定如何选取下一个节点。在介绍A算法之前,需要了解一下什么是以及。

m0_59330466的博客 4577

从帧结构到数据解析:深入理解CJ/T 188 MBUS水表通信协议

本文深入解析CJ/T 188 MBUS水表通信协议,从帧结构到数据解析提供完整指南。通过典型报文示例和实战案例,详细讲解地址域、控制码、数据标识符(DI)等关键字段的解析技巧,并分享校验算法与常见错误排查方法,帮助开发者快速掌握MBUS协议在水表通信中的应用。

weixin_28710999的博客 423

DDR4内存PCB设计实战:8层板Fly-by拓扑信号完整性优化

本文深入探讨了DDR4内存条在8层PCB板上采用Fly-by拓扑时的信号完整性优化实战。文章详细解析了层叠规划、阻抗控制、电源分割、等长布线及串扰抑制等关键设计要点,并强调了仿真验证的重要性,为硬件工程师提供了从理论到实践的完整设计指南与自查清单。

weixin_29296241的博客 340

A*寻路算法(转)

[zz] A*寻路算法 英文原版: http://www.gamedev.net/reference/articles/article2003.asp 中文翻译版: http://www.cppblog.com/christanxw/archive/2006/04/07/

liuchen1206的专栏 1790

通俗傻瓜式理清光栅化渲染和光线追踪渲染的原理

用通俗语言傻瓜式的讲清楚光栅渲染和光线追踪渲染的原理,方便没有相关理论基础的朋友理解入门。

qq_37366618的博客 2万+

A*算法原理与实现

A*算法原理与实现

weixin_50431732的博客 9033

Frida精准定位Shopee x-sap-ri动态签名生成函数

x-sap-ri是Shopee客户端生成的上下文感知型动态令牌,本质为基于设备标识、请求路径与毫秒级时间戳三元组的SHA256哈希值,经Base64编码后作为防重放与防批量伪造的核心校验字段。其生成逻辑深度混淆且跨Java/Native层,静态分析失效,而Frida凭借内存级函数调用拦截与JNI层穿透能力,成为唯一可行的技术路径。本文聚焦Frida在加固App中的实战适配——通过libcrypto.so API特征扫描反向定位被抹名的生成函数,实现对x-sap-ri输入参数(如16字节device_id加密

weixin_33978578的博客 610

Vivado静态时序分析学习笔记(1)

静态时序分析分为片内时序分析(寄存器与寄存器之间的时序关系)和片外时序分析(IO时序分析)。(1)建立时间 setup time在时钟事件(上升沿/下降沿)发生之前数据信号应保持稳定的时间。把实际电路抽象成前级D触发器+组合逻辑+后级D触发器。

Fantaasky的博客 4376

Unity 实现A* 寻路算法

A* 寻路算法在Unity中的示例

YF云飞的博客 1万+

手机直连低轨卫星通信:架构、关键技术和未来展望

【摘 要】借助低轨卫星星座全时全域覆盖优势,手机直连卫星通信预期成为6G重要特征之一。首先介绍了手机直连卫星的测试验证、标准化与商业项目发展现状。其次,介绍了基于透明转发、部分可再生处理、完全可再生处理、集成接入和回传的四种手机直连低轨卫星网络架构及组网方式。通过分析手机直连低轨卫星网络场景下高移动性与大传输时延等带来的接入与传输问题,提出对地面移动通信体制进行适应性改进的关键技术方案。最后,探讨了未来手机直连低轨卫星发展发向和潜在思路。通过上述阐述与分析,提供未来发展手机直连低轨卫星通信的可行路径。【关

fzq0625的博客 1707

unity之A*寻路

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

qq_42345116的博客 3328

025、空间降噪与时域降噪:噪声抑制与细节保留的平衡艺术

《降噪技术的平衡艺术:空间与时域降噪的协同优化》 本文深入探讨了图像处理中空间降噪与时域降噪的技术原理与工程实践。空间降噪通过像素级处理提升单帧质量,而时域降噪则利用帧间信息增强稳定性。文章揭示了两种方法在实际应用中的矛盾点:过度降噪会导致细节损失,影响后续算法性能。作者结合车载环视系统等实战案例,详细分享了参数调优经验,包括运动自适应策略、边缘保持技巧和嵌入式平台优化方案。特别强调降噪的最终目标应服务于下游算法需求,而非单纯追求图像美观。文章为工程人员提供了从理论到实践的完整指导,展现了降噪技术在效果与性

sundong_81的博客 186

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

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

A*寻路算法

转载自:http://www.cppblog.com/christanxw/archive/2006/04/07/5126.html 原文地址:http://www.gamedev.net/reference/articles/article2003.asp 概述 虽然掌握了A*算法的人认为它容易,但是对于初学者来说,A*算法还是很复杂的。 搜索区域(The Search Area) 我们假设某人要从A点移动到B点,但是这两点之间被一堵墙隔开。如图1,绿色是A,红色是...

菜鸡的博客 8339

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

Unity | A*寻路算法

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

持续学习! 4078

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

A*寻路详解

搜索最基本的思路是穷举搜索,例如广度优先和深度优先搜索,但当搜索空间过大,也即可能性太多时,最好可以提供一种方式,对可能性做筛选,减少搜索空间,进而提高搜索效率。常用的说法是cost,从一个点到另外一个点的成本,通常成本就是距离的度量,在机器学习中,还会加上其他因素的度量,寻路算法中只有距离度量。通常来说,搜索是一步步进行的,每一步会将新的可能加入到待处理队列中,如果每一步都从当前可能中选择一个最优的结果,这就是贪心的。游戏中通常需要最快找到该路径(A*算法),而不是找到最短的路径(Dijkstra算法)

enternalstar的博客 1808

A*寻路优化

如果起始点和目标点有一定的距离,那么会存在这样一种情况,一个距离目标点较近的Point和一个距离起点较近的Point,可能有相同的cost,这将导致某次选择出的cost的最小的点距离目标点很近,下次选出的点却距离起始点很近,前后两个点有跳变,为此,可以增加一个舍弃距离。当选出的点与之前的点距离较远时,直接将该点舍弃,重新选择。在D Star中,也会寻找cost最小的点,但路障会改变cost,导致最小的cost点发生变化,此时是在多次的搜索中的最下cost,在D Star中被称为k值。

enternalstar的博客 1158

实用高效的寻路算法——A*寻路算法的实现及优化思路

https://www.fgba.net/sitemap.xml

woliuqiangdong的博客 7613

Unity3D之迷宫寻路_A*最短路径寻路

A*寻路相信很多人都听说过,也是比较基本的一种算法,具体概念我就不多说了,网上查找一下一大堆,我直接贴上我的A*应用方法,以下是地图: 接下来是地图数组: using UnityEngine; using System.Collections; public static class MapsArray { public static int[,] MazeItem = n

0完美对称0的专栏 5266
上一篇: 高级状态机创建
下一篇: iOS之俄罗斯方块
RootTimeYu
博客等级 码龄9年 4粉丝 11原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值