A*多人寻路解决方案及优化策略

这篇博客探讨了在Unity中使用A*算法进行多人寻路时遇到的问题及解决方案。作者提出通过等待和二次寻路策略来避免角色重叠,并介绍了优化方法,如使用二叉堆和缩小寻路范围。文章提供了部分代码,但不包含完整的多人寻路模块。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题外话
  • 去年暑假开始接触Unity,到现在(2019/06/23)已经快一年了,认为自己成长了很多,感觉以前写的代码很丑陋
  • 我的考试周(实际上连续了一个月)已经结束了,嘻嘻嘻
  • 应一位在职美术的邀请,参与了某个游戏的制作,这个也是游戏的一个模块,同时也因为这个原因此篇博客只能提供解决方案和部分代码,给不了项目文件
  • IGG 2019G星计划那个暑期实习,6月14号最终面了,结果需要等到7月5号,真是让人心急啊,当场出结果多爽啊,就算是没过心里也不用惦记着(害怕7月5号那天,邮箱收到“很遗憾…”开头的邮件
如果你点开这篇博客,关于A*的基础知识你一定已经知道了

如果不知道请点击 https://blog.youkuaiyun.com/hitwhylz/article/details/23089415

多人寻路中存在的问题

1.不做任何设置直接寻路,会导致重叠
在这里插入图片描述
2.把周围的点设置为障碍物,直接二次寻路会导致性能消耗过大,额外专门开个线程还好一点

解决办法
说的简单一点就是:等待+二次寻路

这里,我们把需要寻路的“角色”或“人物”称为 Role
具体思路:
1.为每一个Role调用A*实例,得到路径
2.设置CircleCastAll,如果此Role与其他Role产生“碰撞”,进入等待状态,等待计时
3.在等待状态中,对Role的前进方向投射CircleCast,如果前进方向没有其他Role阻拦,继续前进
4.等待计时超过一定限制,根据情况二次寻路,把阻挡的Role设置为“不可通过”(实际上相当于又回到了第一步)
5.如果已经到达目的地,可以根据需求进行排列阵型(小范围寻路)

效果图

在下图中我只点击了一次
在这里插入图片描述
此效果图并没有步骤五的效果,其实我觉得没写View层,从这几个点能看出个鬼,可能因为我不是策划?
在这里插入图片描述

关于优化

1. 使用二叉堆
什么是二叉堆?http://www.ijiandao.com/2b/baijia/168869.html

反例:
去年我初次接触A*的时候,用我魔改的红黑树存的节点,效率也有提高。
面试的时候我还说我的A*数据结构用的红黑树,但没想到有二叉堆这么合适的东西,可恶啊

2. 在二次寻路中缩小寻路范围
3. 二次寻路范围偏移
根据物体与目标的位置进行范围偏移,总结的话就是一张图,尽量合理利用寻路范围
如何做到呢?
这里有点A和点B,我们先求出两点的中点C, 向量Vector = (mapCenterPos-mapStartPos),也就是寻路范围中心点到寻路空间左下角的向量, 我们这次寻路的起点坐标=C+Vector,就可以达到下图中的效果,目的就是最大限度的利用寻路空间。
在这里插入图片描述

关于代码

我在优快云写的第一篇博客就是Unity2D中A*寻路算法,当时初学,年轻不懂事,不知道优化,存储节点用的红黑树(虽然也有性能提升,但是没二叉堆合适),代码复用性也不好
因为项目原因不能提供多人寻路的代码,只提供了新版本A*的代码
其中包含我改好的二叉堆,如果想用的话只需要

MapGrids localMapGrids;
AStarWayFinding wayFind;
List<Vector2> wayList;

//初始化格子
localMapGrids = new MapGrids(mapSize, startPos, mapStep, layerMask);//地图大小,起点,格子大小,碰撞投射层级
wayFind = new AStarWayFinding();
//把路径存储到wayList中
wayList=wayFind.WayFinding(rolePos, targetPos, localMapGrids);

以下是A*寻路所用到的全部代码

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

public class HeapSort
{
   
   
    private OpenlistNode[] array;
    private int currentIndex;

    public HeapSort(int size)
    {
   
   
        array = new OpenlistNode[size];
        currentIndex = 0;
    }
    public OpenlistNode[] getList()
    {
   
   
        return this.array;
    }
    public int getSize()
    {
   
   
        return this.currentIndex;
    }
    //插入
    public void insertSort(OpenlistNode source)
    {
   
   
        array[currentIndex] = source;
        tickedUp(currentIndex++);
    }

    private void tickedUp(int index)
    {
   
   
        int parentIndex = (index - 1) / 2;//父节点索引
        OpenlistNode temp = array[index];
        while (index > 0 && array[parentIndex].F1 > temp.F1)
        {
   
   
            array[index] = array[parentIndex];
            index = parentIndex;
            parentIndex = (parentIndex - 1) / 2;
        }
        array[index] = temp;
    }
    public OpenlistNode getMin()
    {
   
   
        OpenlistNode minNode = array[0];
        array[0] = array[--currentIndex];
        trickleDown(0);
        return minNode;
    }
    private void trickleDown(int index)
    {
   
   
        OpenlistNode temp = array[index];
        int minChildIndex;
        while (index < currentIndex / 2)
        {
   
   
            int leftChildIndex = 2 * index + 1;
            int rightChildIndex = leftChildIndex + 1;

            //右子节点存在,且小于左子节点
            if (rightChildIndex < currentIndex && array[leftChildIndex].F1 > array[rightChildIndex].F1)
            {
   
   
                minChildIndex = rightChildIndex;
            }
            else
            {
   
   
                minChildIndex = leftChildIndex;
            }
            if (temp.F1 <=
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值