zoukankan      html  css  js  c++  java
  • Unity3D 2D游戏中寻径算法的一些解决思路

    需求

    unity3d的3d开发环境中,原生自带了Navigation的组件,可以很便捷快速的实现寻路功能。但是在原生的2d中并没有相同的功能。

    现在国内很多手机游戏都有自动寻路的功能,或者游戏中存在一些例如机器人、npc等,都需要自动寻路的功能。

    我需要实现的功能类似于当年FC游戏中淘金者的运动方式。游戏中有淘金者、敌人,可移动,不可移动区域,只能沿着直线的向前向后或者向上向下。

    思路

    unity3d中也有一些2d寻路的插件。例如A Pathfinding Project Pro和NavMesh 2D。

    两个插件都是收费插件,可以满足不同需求,但是我用过之后发现并不是我想要的效果,而且修改别人的代码的还是挺难受的。所以决定自己写一遍A*算法。

    A*算法已经有很多大牛的博客中,都有非常不错的介绍。我看的是这篇,给大家推荐下:传送

    这篇文章的代码在于拐点的处理上是有一定问题的,我在下面的代码中有进行修改。

    解决方案

     先上结果,实现后的路径是这样的。请忽略那只乱入恐龙,他其实只是来打酱油的~~

    核心代码如下:

     1 public Point FindPath (Point start, Point end, bool IsIgnoreCorner)
     2     {
     3         OpenList.Add (start);
     4         while (OpenList.Count != 0) {
     5             //找出F值最小的点
     6             var tempStart = OpenList.MinPoint ();
     7             OpenList.RemoveAt (0);
     8             CloseList.Add (tempStart);
     9             //找出它相邻的点
    10             var surroundPoints = SurrroundPoints (tempStart, IsIgnoreCorner);
    11             foreach (Point point in surroundPoints) {
    12                 if (OpenList.Exists (point))
    13                         //计算G值, 如果比原来的大, 就什么都不做, 否则设置它的父节点为当前点,并更新G和F
    14                     FoundPoint (tempStart, point);
    15                 else
    16                         //如果它们不在开始列表里, 就加入, 并设置父节点,并计算GHF
    17                     NotFoundPoint (tempStart, end, point);
    18             }
    19             if (OpenList.Get (end) != null)
    20                 return OpenList.Get (end);
    21         }
    22         return OpenList.Get (end);
    23     }

    原文中有些小问题的CanReach方向,我修改的如下:

     1 public bool CanReach (Point start, int x, int y, bool IsIgnoreCorner)
     2     {
     3         if (!CanReach (x, y) || CloseList.Exists (x, y))
     4             return false;
     5         else {
     6             if (Math.Abs (x - start.X) + Math.Abs (y - start.Y) == 1)
     7                 return true;
     8                 //如果是斜方向移动, 判断是否 "拌脚"
     9                 else {
    10                 if (IsIgnoreCorner) {
    11                     if (CanReach (Math.Abs (x - 1), y) && CanReach (x, Math.Abs (y - 1)))
    12                         return true;
    13                     else
    14                         return false;
    15                 } else
    16                     return false;
    17             }
    18         }
    19     }

    总结

     算法还是要多自己写一些,总是拿来主义不利于自己的成长,在大学里学过了,基本都还给老师了,项目里的东西,要用也要明明白白的用,防止为以后的开发留下隐患,到时候从头再找就需要话费给多的时间了。

    项目源代码中包含了spine的例子,所以有点大,有兴趣的朋友可以下载去玩一玩。

    点击下载源代码

  • 相关阅读:
    Anaconda环境下安装库
    数据库定义、性质、演变
    web测试与app测试区别
    黑盒测试用例设计方法
    软件测试黑盒、灰盒、白盒测试的区别
    web端指什么?
    apache、tomcat和svn有什么作用,区别是什么
    H5如何测试?
    软件测试工具
    web与app测试重点
  • 原文地址:https://www.cnblogs.com/nightcat/p/unity3d_005.html
Copyright © 2011-2022 走看看