Unity寻路A星算法

news2024/9/29 21:28:50

文章目录

      • 实现步骤概览:
    • 计算移动成本
      • 1. **定义移动成本函数**:
      • 2. **考虑不同类型的格子**:
      • 3. **动态调整成本**:
      • 4. **实际应用**:
    • 优先级队列
      • 1. **初始化**:
      • 2. **节点评估**:
      • 3. **更新节点状态**:
      • 4. **排序与重复**:
      • 5. **避免重复探索**:
    • Unity C# 实例代码简化版:

在Unity中实现A星(A*,A-Star)算法是一种用于寻找两点之间最短路径的广泛应用的技术。该算法结合了启发式搜索与图论中的Dijkstra算法,通过评估每个节点到起点和终点的成本来确定最优路径。

以下是Unity中使用A*寻路算法的一个简要步骤和实例:

实现步骤概览:

  1. 构建网格:将游戏场景中的可行走区域划分为一个二维网格,每个格子代表一个节点。
  2. 计算移动成本:为每个节点定义从起始点到达该节点的实际代价G值以及到目标点的启发式估计H值,通常采用欧几里得距离、曼哈顿距离或对角线距离等。
  3. 优先级队列:使用优先级队列存储待探索节点,优先级由F值决定(F = G + H)。
  4. 节点状态标记:设置节点状态(如开放列表、关闭列表),以跟踪哪些节点已探索过,哪些正在探索中。
  5. 循环迭代:每次从优先级队列中取出F值最小的节点进行扩展,检查其相邻节点,并更新它们的G值和F值,然后将满足条件的新节点加入开放列表。
  6. 结束条件:当找到目标节点或者没有更多的节点可以探索时,算法结束,回溯生成最终路径。

计算移动成本

在A*寻路算法中,移动成本(也称为代价、权重或消耗)是决定路径选择的关键因素。以下是计算移动成本的详细说明:

1. 定义移动成本函数

在A*寻路中,从一个节点到另一个相邻节点的移动成本通常不是简单的单位距离,而是可以根据地形、障碍物、角色能力等因素来定制。例如,平坦地面可能成本为1,而穿越山地或水域可能成本更高。

设定移动成本的函数可以表示为 Cost(nodeA, nodeB),它接收两个相邻节点作为输入,并返回从nodeA移动到nodeB的成本值。

2. 考虑不同类型的格子

如果场景中有多种类型的地图格子,比如平地、沼泽、山脉等,每种类型的格子可赋予不同的移动成本。

  • 平坦地形:正常行走速度,成本较低,如 cost = 1
  • 沼泽:行走困难,成本较高,如 cost = 2
  • 山脉:攀爬耗时较长,成本更高,如 cost = 3

3. 动态调整成本

成本还可以根据实时条件变化,例如敌人区域可能增加额外风险和成本,或者某些路线在特定条件下变得更快更便宜。

4. 实际应用

在实现过程中,当计算相邻节点的F值(总成本)时,G值会包括前一节点到当前节点的实际移动成本,即 G(currentNode) = G(previousNode) + Cost(previousNode, currentNode)

总之,在A*寻路算法中,移动成本是一个灵活的概念,需要根据具体的游戏环境或实际问题需求来设计和实施。通过合理设置移动成本,算法能够有效地找到最优或接近最优的路径。

优先级队列

在A*寻路算法中,优先级队列扮演着关键角色。它用于存储待探索的节点,并根据每个节点的F值(总成本)来决定接下来应该探索哪个节点。

优先级队列如何工作在A*寻路中:

1. 初始化

首先,将起始节点放入优先级队列中。这个队列通常实现为一个最小堆,这样每次都能快速获取当前F值最小的节点(即最有可能通往目标且代价最低的节点)。

2. 节点评估

每次从优先级队列顶部取出F值最小的节点进行检查。如果该节点是目标节点,则找到了路径并结束搜索;否则,将其相邻的未探索过的节点加入到优先级队列中。

3. 更新节点状态

对于新加入优先级队列的相邻节点,计算其G值(从起点到达该节点的实际代价)、H值(启发式估计值,即到目标节点的预计代价),然后根据公式 F = G + H 计算出F值,并以此作为优先级。

4. 排序与重复

优先级队列会自动按照F值对这些相邻节点进行排序,保证下一次从队列中取出的节点始终具有当前已知的最小F值。

5. 避免重复探索

已经处理过的节点会被标记为“已关闭”,并从优先级队列中移除,以避免无谓的重复探索。

通过这样的机制,A*寻路能够有效地找到从起点到终点的最优或接近最优路径,同时确保了效率,因为它总是优先考虑最有希望的方向。在Unity或者其他游戏开发环境中,优先级队列常常由内置的数据结构如C#中的PriorityQueue类(或通过自定义数据结构结合heapq等库实现)来支持。

Unity C# 实例代码简化版:

using System.Collections.Generic;
using UnityEngine;

public class AStarPathfinding : MonoBehaviour
{
    public Grid grid; // 假设有一个Grid类负责处理网格数据
    public Transform startNode, endNode;

    private List<Node> openList = new List<Node>();
    private HashSet<Node> closedList = new HashSet<Node>();

    public void FindPath()
    {
        Node start = grid.NodeFromWorldPoint(startNode.position);
        Node target = grid.NodeFromWorldPoint(endNode.position);

        openList.Clear();
        closedList.Clear();

        start.G = 0;
        start.H = Heuristic(start, target); // 使用启发式函数计算H值
        start.F = start.G + start.H;

        openList.Add(start);

        while (openList.Count > 0)
        {
            Node currentNode = GetLowestFScore(openList); // 获取F值最低的节点

            if (currentNode == target)
            {
                RetracePath(start, target);
                return;
            }

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

            foreach (var neighbor in grid.GetNeighbors(currentNode))
            {
                if (closedList.Contains(neighbor)) continue;

                int newMovementCostToNeighbor = currentNode.G + GetDistance(currentNode, neighbor);

                if (!openList.Contains(neighbor) || newMovementCostToNeighbor < neighbor.G)
                {
                    neighbor.G = newMovementCostToNeighbor;
                    neighbor.H = Heuristic(neighbor, target);
                    neighbor.parent = currentNode;

                    if (!openList.Contains(neighbor))
                        openList.Add(neighbor);
                }
            }
        }
    }

    private int Heuristic(Node a, Node b)
    {
        // 可能使用曼哈顿距离或其他启发式函数
        return Mathf.Abs(a.GridX - b.GridX) + Mathf.Abs(a.GridY - b.GridY);
    }

    // 其他辅助方法...
}

// Node类表示网格中的单个节点
public class Node
{
    public int GridX, GridY;
    public int G, H, F;
    public Node parent;

    // 其他属性和方法...
}

以上是一个简化版本的A*寻路算法在Unity中的实现概述和实例代码片段。实际应用中可能需要根据具体项目需求进一步完善和优化。例如,Grid类可能包含创建和管理网格节点的方法,而Node类则会包含必要的信息和操作。

python推荐学习汇总连接:
50个开发必备的Python经典脚本(1-10)

50个开发必备的Python经典脚本(11-20)

50个开发必备的Python经典脚本(21-30)

50个开发必备的Python经典脚本(31-40)

50个开发必备的Python经典脚本(41-50)
————————————————

​最后我们放松一下眼睛
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1386484.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

电脑桌面便签在哪设置?备忘录软件哪个好?

好记性不如烂笔头&#xff01;相信很多打工族在电脑面前办公的时候&#xff0c;都需要随时记录工作中的事项&#xff0c;有的用TXT记录&#xff0c;有的手写笔记&#xff0c;还有一些用电脑桌面便签类软件。而当我们待办事项繁多的时候&#xff0c;手写或文本记录并不能有效帮我…

删除运行框中的文件打开历史记录

当我们使用everything、百度、迅雷等软件&#xff0c;在列表中右键选中打开文件夹时。 当使用 winR 快捷键等方式打开运行时&#xff0c;输入盘符会出现之前打开过的文件夹&#xff0c; 一方面展示的特别多会比较混乱&#xff0c;另一方面 记得在之前的window版本中&#xff08…

What is `@Repository` does?

Repository 是Spring注解&#xff0c;标识数据访问层组件&#xff08;DAO, Data Access Object&#xff09; 当一个类被标记为 Repository 时&#xff1a; 1、组件扫描与自动代理&#xff1a; Spring通过组件扫描&#xff08;Component Scan&#xff09;机制发现带有 Reposit…

KEIL MDK 工程(.uvprojx)目录更改后快速修改方法

概述 在项目过多时&#xff0c;为了方便管理&#xff0c; 需借用文件夹命名来&#xff0c;举例&#xff1a; 1、原工程是在“STM32_Test_Project\MDK-ARM”目录下&#xff0c;我现在创建新文件夹&#xff0c;“Test”&#xff0c;避免原来的受污染&#xff0c;或者好管理等等好…

Linux 多个php版本选择需要的php的版本(修改环境变量)

这两天遇到了个问题&#xff0c; 原本服务器的php版本是7.3.13&#xff0c;经过一些操作之后不知道怎么了变成了5.6 #php版本查看 php -v然后我就对 5.6版本进行了升级&#xff0c;升级到了7.3.33&#xff0c; 这个时候 php -v 是7.3.33&#xff0c; 神奇的一幕出现了&#xf…

鸿蒙开发之组合手势

当我们需要支持多个手势的时候&#xff0c;可以通过GestureGroup来实现&#xff0c;如下实现了同时支持Tap和Pan手势 import Prompt from system.prompt Entry Component struct OfficialGestureGroupPage {State message: string Hello Worldbuild() {Column() {Column() {T…

STM32F103标准外设库——认识STM32(一)

个人名片&#xff1a; &#x1f981;作者简介&#xff1a;一名喜欢分享和记录学习的在校大学生 &#x1f42f;个人主页&#xff1a;妄北y &#x1f427;个人QQ&#xff1a;2061314755 &#x1f43b;个人邮箱&#xff1a;2061314755qq.com &#x1f989;个人WeChat&#xff1a;V…

SSH远程访问与控制

目录 ssh优点 作用 SSH的 软件 公钥首次连接原理 ssh远程登录 shh命令 远程连接 直接连接先输入ssh IP 连接指定用户 在 /etc/ssh/sshd_config下面修改端口号 修改服务端配置文件 ​编辑 白名单&#xff0c;只能登录本机的mcb用户 SSH服务的最佳实践 openSSH 服…

Vue.js轻量级框架:快速搭建可扩展的管理系统

一、前言 在项目实战开发中&#xff0c;尤其是大平台系统的搭建&#xff0c;针对不同业务场景&#xff0c;需要为用户多次编写用于录入、修改、展示操作的相应表单页面。一旦表单需求过多&#xff0c;对于开发人员来说&#xff0c;算是一种重复开发&#xff0c;甚至是繁杂的工作…

NetCore部署微服务(三)

接上文&#xff0c;服务端部署完成之后&#xff0c;同样我们也需要修改一下客户端代码 Blocking Queries 1.1 服务发现 在客户端代码中使用Nuget安装consul包 修改配置文件&#xff0c;我们首先需要把consul的请求地址配置在配置文件中 修改control方法 using Consul; usin…

第七在线荣获百灵奖 Buylink Awards 2023零售圈年度卓越服务商品牌

1月11日&#xff0c;由零售圈主办、20零售连锁协会协办、30零售行业媒体支持的中国零售圈大会暨2024未来零售跨年盛典在西安落下帷幕&#xff0c;在这个零售行业盛典中&#xff0c;第七在线凭借其高精尖产品和卓越的服务质量成功入选&#xff0c;并荣获了“百灵奖 Buylink Awar…

旧路由重置新路由设置新路由设置教程|适用于PPPoE拨号

前言 前几天朋友说路由器想要重置&#xff0c;但不知道怎么弄。所以就想着只帮忙重置路由器的话&#xff0c;只能帮到一个人。但把整个过程写成图文&#xff0c;就可以帮助更多人。 本文章适合电脑小白&#xff0c;请注意每一步哦&#xff01; 注意事项 开始之前需要确认光猫…

深度学习环境常用命令(持续更新......)

深度学习涉及常用命令 在深度学习过程中常涉及的命令记录备查。 本文中涉及命令均在windows上&#xff0c;使用Anaconda管理环境的情况下。 显卡环境相关命令 1.pytorch下查看cuda版本&#xff0c;查看cudnn版本 import torch print(torch.version.cuda) print(torch.back…

Docker 如何安装 MySQL 并实现远程连接

Hello各位小伙伴们大家好&#xff01;我是咕噜铁蛋&#xff01;随着云计算和容器化技术的兴起&#xff0c;Docker 已经成为现代软件开发的核心工具之一。它提供了一种轻量级、可移植、自包含的部署方式&#xff0c;使得开发人员可以更加便捷地构建、测试和发布应用程序。而 MyS…

docker安装部署Elasticsearch(ES)以及相关配置

Elasticsearch简介 mysql用作持久化存储&#xff0c;ES用作检索 基本概念&#xff1a;index库>type表>document文档 index索引&#xff08;相当于MySQL的数据库&#xff09; 动词&#xff1a;相当于mysql的insert 名词&#xff1a;相当于mysql的db Type类型&#xff…

Rust-借用检查

Rust语言的核心特点是&#xff1a;在没有放弃对内存的直接控制力的情况下&#xff0c;实现了内存安全。 所谓对内存的直接控制能力&#xff0c;前文已经有所展示&#xff1a;可以自行决定内存布局&#xff0c;包括在栈上分配内存&#xff0c;还是在堆上分配内存&#xff1b;支…

【开发篇】三、并发下的OOM分析

文章目录 1、并发下的OOM分析2、Jmeter模拟并发 1、并发下的OOM分析 用户请求过来&#xff0c; 后端查询数据库后封装Vo对象返回给前端后&#xff0c;然后正常这个Vo就可以被GC清理掉了。 但并发时&#xff0c;如果数据处理时间很长&#xff0c;大量对象存于内存&#xff0c;或…

开源28181协议视频平台搭建流程

最近项目中用到流媒体平台&#xff0c;java平台负责信令部分&#xff0c;c平台负责流媒体处理&#xff0c;找了评分比较好的开源项目 https://gitee.com/pan648540858/wvp-GB28181-pro 流媒体服务基于 c写的 https://github.com/ZLMediaKit/ZLMediaKit 说明文档&#xff1a;h…

web前端(第二次作业)

1、计算用户指定的数值内的奇数和。例如用户输入的是 10&#xff0c;则计算 1 3 5 7 9 的和 <!DOCTYPE html> <html><head><meta charset"utf-8"><title></title><script>var nprompt("请输入数值&#xff1a;&…

基于信号完整性的一些PCB设计建议

最小化单根信号线质量的一些PCB设计建议 1. 使用受控阻抗线&#xff1b; 2. 理想情况下&#xff0c;所有信号都应该使用完整的电源或地平面作为其返回路径&#xff0c;关键信号则使用地平面作为返回路径&#xff1b; 3. 信号的返回参考面发生变化时&#xff0c;在尽可能接近…