Q1:我们在做一个RTS游戏,开始用的是Unity自带的NavMesh的寻路,但发现这个并不适合RTS多人寻路,因为总会出现阻挡和闪跳的问题。看Asset Store上的A* path插件评论说在碰撞上有问题,不知道大家是否能提供比较成熟的解决方案?

我们上一个项目是RTS项目,刚开始寻路问题解决方案过程中遇到过和你相似的疑惑,修改探索和调教了很长时间,分享几点供题主参考下。

先上结论:我们采用了两层结构 A Start Pathfinding Project Pro + Unity NavMesh。

1)主体寻路方案使用 A Start Pathfinding Project Pro 这个插件中传统的网格形式,并进行了深度修改扩展,主要是满足寻路过程的通路性需要考虑到单位半径大小,这样寻路精度高;

2)使用Unity NavMesh系统作为寻路过程中的碰撞系统,因为你说的很对,这个寻路插件的碰撞有问题,稍后解释。

以上两部分组成“寻路算法+精确碰撞”。接下来说下以上方案的原因和细节。

1、NavMesh寻路速度快但不够精确。RTS还是适合使用传统的四方形NavGrid格子寻路,而且现有的任何寻路算法默认都是不支持考虑寻路单位半径大小对寻路过程的影响,但我们策划绝不允许1米宽的缝隙被一个两米宽的胖子挤过去,如果使用Navmesh并且动态生成阻挡会出现寻路路径是有了,可是由于碰撞问题大的单位会卡在缝隙这里来回“发抖”的情况;这个只能自己动手修改,所以我们买了该插件然后自己从里到外修改,具体修改算法原理和修改后的示意图,你可以参考这里:http://www.cnblogs.com/yaukey/p/rts_unit_traverse_size_based_path_finding.html
修改完后,每次寻路会将单位的直径大小当做寻路参数之一传入进行寻路。

使用这个插件开启两个线程左右来寻路是我后来调教出的、一个比较理想的结果。然后是地图中各种单位会出生和死亡,当单位站定不动,需要生成阻挡;移动了需要移除阻挡恢复此处的通路性,通过再修改下插件中的DynamicObscule这个组件(原生功能太简单)来实现;我们具体是每个单位都有一个对应的大小的CapsuleCollider空对象挂上这个脚本,单位站定将该物体放置到单位的位置并激活它,单位移动隐藏该空物体即可,这个脚本会引起地图通路性的更新,这个更新是多线程的,这一点是要注意的,通过回调事件来做响应的事情,切记不要在同一帧或者下一帧去做,因为即时性不能保证。这样就能让整个地图一直根据单位来更新通路性。

2、寻路的通路性问题解决了,现在来解决碰撞问题。这个插件自带了碰撞算法,使用的rvo算法,但是据我当初各种调教实验,它的碰撞都达不到我们的要求,单位多了拥挤的时候总是会有些单位站立后变得重叠了,最不能接受的是两个单位完全重叠。在这里我花了相当多的时间都不能修改出的满意的效果。后来想起来recastnavigation作者亲口说过虽然Unity的NavMesh基于此,但是Detour系统经过深度的改写,Detour包含了巡航和碰撞,而实际使用也发现NavMeshAgent之间的碰撞是很精确的,于是我想了个取巧的办法,给地表再铺一层跟AStar插件的寻路面积一样大的NavMesh,但是没有任何的阻挡(理解为一片纯蓝色),同时给寻路单位添加一个NavMeshAgent,然而这个东西只用它的碰撞,而不使用寻路(没有阻挡,任何寻路都是两点直线,可以考虑几乎无开销),这样最后实际的碰撞效果才算达到我们满意的效果。

以上就是我所说的两层含义,我再说下坑和问题。

1)当初开发Unity版本是Unity
5.3.7-5.3.8,插件版本5.x,寻路插件中底层会有Physics.CheckCapsule调用,但是多线程大量调用,会导致底层PhysX物理引擎崩溃,游戏闪退,不必现但是大量的话很容易一下就挂,插件官方论坛也有这个Bug讨论,后来我将此换成了两个
Physics.CheckSphere 调用,目前2017版本没有测试过;

2)我在1中使用的方法,在UWA性能评测中,每次都是Dynamic Collider超标,这个需要自己取舍了,但是总体我们游戏的瓶颈不在寻路一块,消耗在这些测试中看来比较理想;

3)插件中由于是多线程更新,有很多的完成事件回调,基本都是利用这些链接游戏系统中,不够了自己加,否则依然是容易在未更新完成时得到错误的结果;

4)有可能的话再优化下内部的一些堆内存分配,并且和游戏系统结合后注意释放和断开引用,否则容易内存泄漏,造成寻路插件被引用以至于后面引用很长一串对象都不得释放;

5)寻路精度和碰撞精度在游戏中的表现,需要花比较多的时间去调教参数,有时候表现不好未必是方案不好,然后如果你们对实时同步性要求较高,这个方案还必须再进一步完善和扩展下。

我们使用这个寻路方案的项目是:《战地指挥官》,你可以下载看看寻路是否符合你的要求,苹果安卓各平台都有。以上是我暂时想起来的一些心得,希望对题主有所帮助:)

感谢Yaukey@UWA问答社区提供了回答,欢迎大家转至社区进行进一步交流:

https://answer.uwa4d.com/question/5ad0553b910222635366dd34

如何制作RTS游戏的寻路系统?的更多相关文章

  1. Atitit 游戏引擎---物理系统(1)------爆炸效果

    Atitit 游戏引擎---物理系统(1)------爆炸效果 1.1. 动画框架的来源flex,jqueryuijs,anim , cocos2d 1 1.2. Jqueryui的特效库 1 1.3 ...

  2. Unity3D RTS游戏中帧同步实现

    帧同步技术是早期RTS游戏常用的一种同步技术,本篇文章要给大家介绍的是RTX游戏中帧同步实现,帧同步是一种前后端数据同步的方式,一般应用于对实时性要求很高的网络游戏,想要了解更多帧同步的知识,继续往下 ...

  3. Unity3D学习笔记(十五):寻路系统

    动画生硬切换:animation.play();//极少使用,常用融合方法 动画融合淡入:animation.CrossFade(“Idle”, 0.2f);//0.2f为与前一动画的融合百分比为20 ...

  4. Spine应用--使用Spine动画制作动作游戏

    在前面的文章中,已经陆陆续续的讲解了一些使用Spine动画的细节,有了这些细节,我们已经满足了在unity中使用Spine动画制作动作游戏的技术基础. 那么,要使用Spine动画在unity中制作一款 ...

  5. 使用CocosSharp制作一个游戏 - CocosSharp中文教程

    注:本教程翻译自官方<Walkthrough - Building a game with CocosSharp>,官方教程有很多地方说的不够详细,或者代码不全,导致无法继续,本人在看了G ...

  6. Cocos2d-x v3.6制作射箭游戏(二)

    原文 Cocos2d-x v3.6制作射箭游戏(二) 六 24, 2015by RENSHANin COCOS2D-X 上章我们创建并加载了游戏地图,接下来的两章我们将实现如下的效果. 在开始之前,先 ...

  7. 制作OpenStack用的RHEL7系统镜像

    制作OpenStack使用的RHEL7系统镜像,并进行相关设置,安装XRDP以进行远程访问. 1.在KVM中安装RHEL7.2客户机: 2.设置网卡为dhcp并onboot=yes,使得虚拟机能自动获 ...

  8. [Mugeda HTML5技术教程之14]案例分析:制作网页游戏

    本文档要分析的案例是一个爱消除的网页小游戏,从中可以体会一些Mugeda API的用法和使用Mugeda动画制作网页游戏的方法. (一)游戏规则: 1.开始游戏时,手机出现在最上面一行的任意一格: 2 ...

  9. 制作macOS10.12系列的系统镜像文件

    制作macOS10.12系列的系统镜像文件步骤,过程也比较简单,十来个命令.以10.12.6为例,首先,在苹果商店下载系统安装包APP,或者网上下载后把安装APP复制到  应用程序  文件夹. 然后打 ...

随机推荐

  1. AngularJs编辑器

    问题:在使用过程中遇到的问题就是:angularJS绑定不上值.后来找到一种可以用的方式. html页 <div class="all"> <script typ ...

  2. JAVA Thread Dumps 三部曲

    一.windows环境下方法 1:cmd下找到运行服务器容器的PID jps -v 例: C:\Users\Administrator>jps -v4856 Bootstrap -Djdk.tl ...

  3. 1.redis设计与实现--简单动态字符串

    1.redis没有使用c语言的字符串表示,而是使用更加适合自己的SDS(simple dynamic string),简单动态字符串,结构如下: 2.sys与c字符串的对比: 3.总结: redis采 ...

  4. 用trigger触发datepicker

    jQuery UI的datepicker没有icon图片,工作需要,自己写了一个,原理是用div包裹住datepicker的input和一个button,隐藏掉input,而button被点击后也可以 ...

  5. [php]require&require_once&include&include_once的用法与区别

    1.require和include是php引入php文件的两种方式,使用格式如下: require(include) 文件名; require(include) 变量(此变量存储的是文件名); 2.区 ...

  6. javascript 中的 this 关键字详解

    1.javascript 中 什么是 this? this 指的是当前行为执行的主体,或者是当前方法执行的主体 context:是当前行为或者方法执行的环境 实例: xx 去北京饭店吃东西:上下文是“ ...

  7. div遮罩实现禁用鼠标(click、hover等)事件

    这两天在帮老师做网页,今天想实现在一块区域内禁止鼠标的各种事件,本来是想在框架模板的js文件里去修改,但是改代码的时候有点凌乱...感觉应该自己把问题想复杂了. 所以想了想要是能实现在一个区域内(如: ...

  8. linux设备驱动模型-浅析-转

    1.  typeof typeof并非ISO C的关键字,而是gcc对C的一个扩展.typeof是一个关键字(类似sizeof),用于获取一个表达式的类型. 举个简单的例子: char tt; typ ...

  9. Mysql 中 char 、varchar 、text的区别

    首先它们的存储方式和数据的检索方式都不一样.数据的检索效率是:char > varchar > text 空间占用方面,就要具体情况具体分析了. char:存储定长数据很方便,CHAR字段 ...

  10. Minimum Palindromic Factorization(最少回文串分割)

    Minimum Palindromic Factorization(最少回文串分割) 以下内容大部分(可以说除了关于回文树的部分)来自论文A Subquadratic Algorithm for Mi ...