C# hash算法 bloom_RTS游戏中的避障算法

概述

继续上一篇寻路算法,本篇介绍RTS游戏中的避障算法,游戏中采用的算法为Optimal Reciprocal Collision Avoidance,简称ORCA。

在一般游戏中,寻路和单位之间的物理碰撞可以解决大多数问题,但在RTS游戏中,尤其是单位还特别多的时候,靠寻路和物理会让所有单位的移动看起来杂乱无章,互相影响。而且寻路还有一个问题,友军是否算寻路过程中的阻挡?在一些典型的RTS游戏中,比如《魔兽争霸3》,单位在寻路过程中是不会将友军视为地形阻挡的,只有在移动的过程中,如果发现当前位置被友军阻挡,那么就会触发一次将友军视为阻挡的寻路。仔细观察这些经典的RTS游戏,都是通过一些小技巧让寻路看起来比较自然。

在我们的这个RTS游戏中,没用物理,而是直接用寻路和ORCA来控制单位移动,有两个原因:1.自研引擎的暂时没有接入物理引擎 2.没有物理,但直接用ORCA看起来也还不错,性能消耗也低。

ORCA相关参考链接为:

  1. ORCA论文

http://gamma.cs.unc.edu/ORCA/publications/ORCA.pdf

  1. 官方文档

http://gamma.cs.unc.edu/ORCA/

  1. ORCA源码,包括C++、C#、Java以及ORCA 3D版本

https://github.com/snape

  1. Unity中ORCA的集成实现

https://github.com/wangjiong/ORCA

  1. 论文笔记《Reciprocal n-body Collision Avoidance》http://www.meltycriss.com/2017/01/13/paper-rvo/http://www.meltycriss.com/2017/01/14/paper-orca/
  2. 论文笔记《Reciprocal Velocity Obstacles for Real-Time Multi-Agent Navigation》

http://www.meltycriss.com/2017/01/13/paper-rvo/

底层避障算法

经典的底层避障算法有3种:

  1. VO(Velocity Obstacle)
  2. RVO(Reciprocal Velocity Obstacle)
  3. ORCA(Optimal Reciprocal Collision Avoidance)

在介绍VO,RVO,ORCA之前,需要先介绍路径规划。

对Agent进行路径规划,实际上要完成的任务就是让Agent从点A无碰撞地移动到点B。而路径规划的过程是层次化的,其基本框架大致如下:

High level: dijkstra、A*等寻路算法。

Low level: VO, RVO, ORCA等底层避障算法。

很容易可以跟我们的日常生活进行类比,比如说我们要从学校的教学楼走到宿舍楼,那么以上框架对应的就是:

High level: 通过dijkstra算法,得到路径为: 教学楼→饭堂→体育馆→图书馆→宿舍楼。

Low level: 通过底层避障算法如VO,RVO,ORCA等底层避障算法,保证我们走的每一段路(e.g. 教学楼→饭堂),都不会跟别的同学发生碰撞。

VO、RVO、ORCA就是经典的底层避障算法。其中VO是最经典的,RVO则在VO的基础上进行了一些改进,解决了VO抖动的问题。

跟RVO一样,ORCA也是基于VO的,但更加实用,因为:

效果上:考虑了速度的大小,使得筛选粒度更细,不像VO和RVO只考虑速度方向。

效率上:求解过程基本只用到了线性规划,比较高效。不像VO和RVO有大量的非线 性求解。

ORCA介绍

723a50aca7ddd719723687c37fec9823.png

具体论证过程参考论文和论文笔记。

ORCA实际上是在ROV做了一步升级,也可称之为ROV2。通过引入一个时间窗口,将相对位置转化成了速度,这样计算最优速度的时候就都在同一个速度坐标系中了。ORCA在计算最优解的时候,需要保证计算出来的速度对双方都是最优解,最终的计算出来的速度可以用一个线性空间表示。针对每一个邻居都有一个这样的线性空间,最终对所有线性空间用线性规划求出最优解,这里可以选择是速度大小优先或速度方向优先。

另外还有一种无解的情况,出现了这种情况,ORCA计算的最终速度并不是0,而是根据邻居的速度空间计算一个最小影响邻居最优解的速度,表现出来的就是随邻居移动。

ORCA的使用及优化

在运用ORCA到游戏的过程中,有4个问题需要重点解决:

  1. ORCA的输入参数需要针对游戏进行调整
  2. 原版ORCA在解决大规模单位避障的时候,在行军和整队的时候,不够流畅
  3. 原版ORCA对所有单位一视同仁,没要考虑有些单位需要强制穿插移动
  4. 抖动问题

针对第一个问题,在RTS游戏中,正常的移动流程是:1.寻敌 2.寻路 3.使用ORCA计算最终移动速度,传给ORCA的参数有7个,如下图所示:

1e77d0430adf4f84f019c1c8635a68bb.png

neighborDist:在寻找周围邻居的搜索距离,这个值设置过大,会让小球在很远 距离的时候做出避障行为。

maxNeighbors:寻找周围邻居的最大数目,这个值设置越大,最终计算的速度越 精确,但会加大计算量。

timeHorizon:代表计算动态的物体时的时间窗口。

timeHorizonObst:代表计算静态的物体时的时间窗口,比如在RTS游戏中,小兵 向城墙移动时,没必要做出避障,这个值需要设置的很小。

radius:代表计算ORCA时的小球的半径,这个值不一定与小球实际显示的半径 一样,偏小有利于小球移动顺畅。

maxSpeed:小球最大速度值

velocity:小球初始速度

针对第二个问题,关于ORCA移动穿插和重叠的问题,表现在游戏中就是

如何保证小兵在移动过程中可以流畅穿插并且在战斗时不会重叠,解决方案有两种:

1.保证小兵的半径固定

优点:可以保证小兵战斗时不会重叠

缺点:无法保证小兵在移动过程中流畅穿插

2.动态改变小兵半径

优点:可以保证小兵在移动过程中流畅穿插

缺点:无法保证小兵战斗时不会重叠

在实际过程中,上面两种方案都无法提高游戏体验,最终的做法是融合了两种方案:同队小兵在计算ORCA时保证半径固定,不同队的小兵在计算ORCA时,在计算过程中,缩小各自的半径。另外,小兵在计算ORCA时,不考虑不同阵营的小兵位置和速度。

针对第三个问题,引入了质量概念,质量大的物体,在使用ORCA计算速度时,自己的优先速度趋向于输入的优先速度,邻居的优先速度趋向于原始速度。核心代码如下:

f702bce1da206fb02db49cab495d3a47.png

针对第四个问题,抖动其实一直没有好的解决,不过有一些方案可以缓解抖动,比如体型大的物体在转向时,不能直接转向,而是增加了一个转向插值,这样的表现过程使得抖动相对而言比较平滑,体型小的物体抖动无法有效的避免,不过因为其数量众多,体型小,频繁抖动也不是很影响体验。

总结

先上传点视频,以后补充

8d41413cb4b2496770e13ab42fd26ddb.png
https://www.zhihu.com/video/1216467259969187840
bac49cbc9c8878bcf55a02eda37e8b79.png
https://www.zhihu.com/video/1216467322246090752
4cfbde6da71f8aafd434360063279be8.png
https://www.zhihu.com/video/1216467356626747392
84ce6705255f6654f40763c72119d8fb.png
https://www.zhihu.com/video/1216467392278564864
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值