Unity AI行为之群组行为之群集动画

发表于2018-09-30
评论0 1k浏览

想免费获取内部独家PPT资料库?观看行业大牛直播?点击加入腾讯游戏学院游戏美术行业精英群

167422913
一、群集动画的简介

群落运动是自然界中非常有趣的现象。在天空中,我们可以看见大群的候鸟南飞,在陆地上,我们可以看见羚羊群,牛群在飞快的奔跑,在海洋里,鱼群的运动更是壮观。群落和其他相关的群体,他们运动的时候都是非常的壮观,他们的气势常常让我们惊叹不已。在群落中,每一个个体都是非常的独立,然而整个群落又犹如一个整体。群体中的个体似乎是随机的,但确有一定的运动规律。最令我们感到震惊的是群落中似乎有一种中央控制,这种控制可以使每一个个体之间保持一定的距离,具有大致相同的运动方向,整个群落运动是建立在每一个个体的运动之上的,个体通过对环境的感知,来调整自己的运动方向以及各种状态。

群体在遇到障碍物的时候,还能自动绕开障碍物,然后重新汇聚在一起,这是一个非常有趣的现象。在一些海底世界的纪录片中,我们常常可以看见鱼群绕过珊瑚礁的美丽情景,就如水遇到石头,绕过然后又汇集在一起。

群体在遇到危险,比如说遇到天敌的时候,群落中的个体开始四散逃窜,同样也是一个壮观的景象。在表面上看起来非常杂乱,但内里也有规律可循----原来的群体分成几个小的群体,向不同的方向逃离。

在动画制作中,我们常常需要制作大规模的生物运动,使整个动画看起来有气势一点。制作这样群落动画,如果给个体单独地添加运动路径,虽然也可以实现,但是这样的代价太大了。如果群体个体数量较少的时候,动画师还可以承受,但是如果成千上万的个体,那这样实现起来就不可能了。而且使用路径动画时,个体被限制在路径上,非常不自由,非常机械,看起来僵硬,不像群落,缺乏个体的意识。因此,我们要研究群落的规律,利用这些规律,去建立一个群落系统,让群落中的每一个个体都具有一定的判断能力,使它具有某种程度上的智能,按照特定的规律进行运动。我们所需要控制的只是群体的宏观属性,比如控制群体的整体运动方向,然后给每一个个体的运动都有那么一点随机的变化,整个群体动画看起来就可以比较可信了,接近我们所需要的效果。我们还可以做得更加细致一点,让群体中的个体有各种习性,比如进食,求偶,追逐等等。这样我们的群落动画就更加生动了,而我们的艺术家工作也就大大减少,可以专注在主要角色的设计和场景的设计了。

二.群集动画的发展

在计算机图形学中,很早就有人模拟鸟群的飞行运动。在1985年的SIGGRAPH展览会上,来自俄亥俄大学计算机图形学研究小组的Susan Amakraut,Michael Girard,和George Karl就展示了一个小小的动画,名字叫“Motion studiesfor a work in progress entitled ‘Eurthmy’”。在这个动画影片中,一群鸟从鸟笼里面飞出来,穿过一系列的圆柱,然后落在操场上。在飞行的时候,每一只鸟都拍动翅膀,并且避免与其他的同伴相碰。这个动画说是使用的技术称为“力场动画系统”,力场是由一个3*3的矩阵表示物体的加速度,它可以将一个点从空间的一个点移到另外一个点。每一只鸟和障碍物之间都有一种排斥力。每一个环绕鸟的力场都有一个边界盒,那么物体之间的碰撞就可以通过边界盒来进行判断。他们使用的是一个增量,线性时间的算法来检测边界框的碰撞。动画师只需要定义空间的力场,设置个体初始位置,方向和速度,以后的所有模拟都是由计算机计算的。

一个比较经典的生命模拟就是有CraigReynold 1987年建立的Boid。Boid是人工鸟,它有最基本的飞行能力,和几种简单的行为,他们可以进行群落运动。如果群落遇到障碍物,群落就会分成两部分,越过障碍以后,又重新聚集在一起。这些都是人工生命如flock,school,或者herd的最重要的特性。

MIT的媒体实验室也曾经建立过一些行为控制动画,比如说宇宙飞船,蠕虫,和四足动物,但是他们不是以群落来组织这些物体的。也有一些人建议使用分布式行为模型去模拟群落行为。另外一个比较着名的例子就是1996发行的娱乐软件Creature,到1999年为止,已经售出了500000份。在他们的论文 “The Creature Global Digital Ecosystem”,Cliff和Gland讨论为什么Creature这个软件会如此的成功,以及他所引起的对于人工生命的极大兴趣,他们还谈到了creature运行机制。在每一个agent中(agent时指人工生命的个体),都运行着一个网络系统,他这个网络系统会受到agent的意识影响。他们使用的是遗传算法。

三、群集动画与粒子系统

群集动画与粒子系统有许多相同的地方,比如说,两者都是描述大规模个体的运动,每个个体的运动都是不规律和复杂的。粒子系统是用来描述像火,烟,云,沙,浪花等等现象,它由大量的粒子组成,每一个都有他自己的属性。粒子有年龄,在他们的生长期内,他们可以通过自己的各种变化,如位置变化,颜色,透明度,速度,来影响整个系统的形态,粒子系统可能就是群集动画的一个雏形吧。但是,群集中的个体行为要比粒子系统中的粒子要复杂得多(当然群集的个体行为不可能像真正的生物那么复杂),而且粒子系统与群集动画的一个非常重要的差别就在于,群集动画中的个体是有形体的节点的,而粒子系统中的粒子却是没有形体节点,它是一个2.5维的系统,没有自己的局部空间。虽然一些动画软件中,像MAYA,XSI可以给粒子系统添加实例对象,让粒子看起来有形体,但实际上它没有自己的局部坐标空间,不能进行更加复杂的形变,只能通过实例对象来完成对形体的修改。而且像

MAYA的粒子系统,粒子与粒子之间不能够检测碰撞,只能通过增加一些放射力场来阻止粒子之间的相互碰撞。不过随着软件的不断发展,粒子系统也不断得到完善,粒子的智能化程度也越来越高,像在《MUMMY RETURN》,就用到了智能粒子。虽然粒子系统与群集动画相比还是差很远,但我们可以借鉴粒子系统的许多特性和规则的,去建造我们的群落动画系统。

四、群集动画的基本规则

在设计群集动画的时候,由一些基本原则是我们需要制定的。只有满足这些要求,我们才能基本建构出我们的动画系统。在群集动画的模拟过程中,系统会模拟群集中个体最基本的能力。群集动画中的每一个个体,都可以根据群落中其他个体的运动来决定自己的运动路径。建立一个群落动画并不是太难,但是我们必须遵循三条规则:

规则一:群落中每一个个体都必须有他自己的个人空间,如果其他的个体进入了这个安全空间,个体就要远离,从而保持个人空间不被侵占。

规则二:群落中的个体都尽量保持与群落中的其他个体运动方向保持一致。也就是说,每一个个体的运动方向是大致相同的。

规则三:每一个小的群落,如果有机会的话,假设附近没有障碍物,都会尝试与附近的群落融为一体。这在群落遇到障碍物分开,越过障碍物后又合在一起的情况时是非常重要。

最后,还需要检测每一个个体与边界的碰撞。为什么要定义边界呢?因为在后面提到一种优化算法,这种算法将会把有限的空间划分成一个个小单元,但是不可能将整个空间都进行划分,因为这需要大量的数据存储,所以限定一个区域,这样算法数据量就可以大大减少了。

五、群集动画实现技术细节

1、群集动画的数学知识

群集动画的数学知识并不复杂,只要满足上面所提到的三条基本规则就可以了。

需要解决的第一个问题就是分离,也就是对每一个个体都进行碰撞检测,使个体们不会挤在一起。如前所述,每一个个体有它自己的个人空间,如果其他个体进入了这个空间,个体就会尝试离开对方,直到距离合适为止。我们可以设置一个标量,这个标量是由个体与其他个体的距离所决定的,距离别的个体的越远,所受的影响也就越小,也就是说与距离成反比。我们可以看看一下公式。


在上面的公式中,velj指的是当前检测个体的运动速度,n是指群落中个体的个数,S这个变量可以控制群落的聚集程度,S的值是在0和1之间,S越大,它受其他个体运动的影响也就越大,整个群落也就趋向于分离,S值越小,个体保持自身运动的趋势就越大。veli

是指其他个体的运动速度。从上面的公式可以看出来,与个体距离越远的个体,它对个体的影响也就越小,反之越大。S值越小,个体保持自身运动的趋势就越大。

个体的下一种行为就是保持与其他个体的方向一致,在现实世界中,你可以看见鱼群在前进的时候,总是保持同样的运动方向,方向改变的时候,所有的鱼几乎都是同步改变方向的。要解决这个问题,只要取它们邻近个体速度的平均方向,乘一个百分比系数S,然后再加上他自己的速度乘以1-S作为个体的新速度:

同样,从上面的公式我们可以看出,S越大,个体就趋向于与其他的个体运动方向一致,S越小,就越趋向于保持自己的运动方向。群落中最后的一个行为就是聚集。对于这个问题,我们只要求出整个群集的中心位置在哪里,然后用一个常数乘以个体到群集中心的向量posj,就可以得出个体向中心靠拢的速度了。

有一点我们需要注意的是,我们所求出来的向量velj可能会非常大,我们需要做的事情是,首先把它进行单位化,乘以一个最大速度vmax,然后再加到结果中。这样我们就可以得到比较好的结果。

接着下来,我们会面临这样一个问题,就是我们的个体如果一开始运动方向是一致的话,所有的运动速度都是一样,那么很可能在以后的检测中,无论怎样计算,都不会再改变个体的运动方向。对于这样的问题,我们只需要在初始化中,让每一个个体的运动方向都有那么一点点不同就可以避免掉。

我们还要考虑一个问题,这三种检测,有可能会出像这样一种情况,就是处于一种平衡状态,也就是他们计算出来的运动变化互相抵消掉了。这种情况会一直持续到出现障碍物碰撞检测,或者是重新设置运动初始值。如果是这样的话,我们的群落动画就不那么生动了。我们怎么才能够解决这个问题呢?如果要设置更加复杂的算法的话,那么开销实在是太大了。还记得公式中有一个S,我们可以利用这个S,对于每一个不同类型的检测,分别设不同的S值,这样我们就可以控制各种不同的状态了。比如说,在碰撞检测中的S增大,而在第三个检测中S减少,我们的群落就趋向分离,反之,我们的群落就趋向于密集。我们还可以在每一轮的检测中,随机的给S附值,这样,我们就可以得到合适的动画效果了。

六、群集动画中碰撞问题

在群集动画中,我们还需要解决个体与障碍物的碰撞问题,有了障碍物的设置,我们的群落运动会变得更加无规则,同时会使动画本身变得更加有意思,试想一下,一群鱼遇到障碍物,鱼群避开障碍物,分成两个小的群落,越过障碍物以后,又重新聚成一个群落,那将是非常有趣的景象。

但是,障碍物检测是一个头疼的问题。在群集动画中的碰撞检测中,我们通常不直接对个体与障碍物进行检测,即通过个体与障碍物的表面进行碰撞检测,虽然是可行的,但是它付出的代价是非常巨大的,因为这意味着需要对组成障碍物的所有表面的多边形进行碰撞检测,这计算量是相当可观的。另外,这种算法的难度也是非常高的。所以,我们需要使用别的方法来减少计算量。

我们通常会使用物体的边界盒来代替障碍物进行碰撞检测,这样,我们只需要对边界盒的六个面进行碰撞检测即可。但是,这样的程序也是相当繁琐的,我们还可以把边界盒简化成长宽一样,高度是无限的长方体进行检测,那么我们仅仅需要对边界盒的四个面进行碰撞检测即可。这样物体的碰撞检测就可以简化成如下图所示:

与四个面进行碰撞检测还是麻烦。我们再次对碰撞进行简化,把障碍物变成一个边界圆柱,并且忽略掉圆柱的高度,这样,原来三维的碰撞就转换成二维平面上的碰撞检测了。如下图所示:

这样,我们就可以通过计算物体到圆心的距离,来判断物体是否会与障碍物碰撞,但是这样还不足以判断物体是否会碰上障碍物。如下图所示,我们还需要判断是否个体的运动方向是否会落入碰撞范围之内,如下图所示,如果∠VBO小于∠ABO,那么个体就会落入物体的碰撞范围之内。

好,如果物体落入碰撞检测的范围之内,那么我们怎样改变个体的运动方向呢?有多种方法,但是在这里,我们使障碍物有一种排斥力(从另一种角度来说是个体具有一种偏离障碍物的能力),个体离障碍物的距离越小,排斥力也就越大。这个排斥力的方向是与物体的运动速度方向垂直。那么问题又出来?物体是向哪个方向偏移呢?如上图所示,当物体运动方向在物体与障碍物连线的上方时,物体是向上偏移,反之向下。如何判断呢?我们只要判断矢量VB与OB的叉积方向就可以了。

接下来,我们还有一个问题没有解决的,我们还需要判断物体是远离障碍物还是接近障碍物,如果物体远离障碍物的话,那么我们就不需要给物体加排斥力了。解决这个问题的方法也是非常简单的,我们只要判断向量VB与OB的点积是正是负就可以了,如果是正值,物体在接近障碍物,如果为负值,物体在远离障碍物。在群集动画中,我们还有一种检测障碍物的方法,就是使用贴图。这种方法比较适合于平地上或者是平面上的群落运动,如蚂蚁群落,四足动物群落。这种碰撞检测对于凹凸地表的检测是最合适的。我们利用一张黑白贴图,黑色的地方表示有障碍物,白色的地方没有障碍物。我们在地表移动物体的时候,不使用物体的空间坐标,而是使用物体在地表平面上的UV纹理贴图坐标,利用UV坐标,我们可以在地表上移动物体,还可以获取物体在该纹理坐标上贴图的颜色,通过颜色,我们可以判断附近是否有障碍物。如果是黑色,表示有障碍物,做出相应的处理。这种黑白纹理贴图在许多好莱坞大片的群落动画中都使用过,比如说《木乃伊》和《指环王》。比如说《指环王》里面,就是用一张黑白贴图来决定过护城桥时,哪些士兵会掉进水里面。这样,整个算法会变得很简单,算法的复杂度也大大下降。

七、群集动画中流程问题

对于群集动画,它有那么多种检测,既有与障碍物的碰撞检测,也有与其他个体的碰撞检测,同时还要保持与群体中其他个体的速度大致一致,还要向群落中心集中,这所有的检测,有没有一个先后顺序呢?答案是有的。那么它们的先后顺序是怎样呢?我们来看看吧。

设个体的原速度是V,所有个体的速度存储在数组V[]中每一种检测,都有它的优先等级,我们首先要进行的是碰撞检测。为什么呢?因为“碰上障碍物”是最危险的,所以他的等级也是最高的。我们通过检测碰撞,计算出碰撞之后的速度变化⊿V1。其次是与其他个体之间的碰撞检测,这时我们检测物体说使用的速度,是没有进行检测前的速度,也就是说还是V。利用它我们可计算出⊿V2。接着下来,我们再计算出对齐检测、靠拢检测的⊿V3,⊿V4。这样,我们对这些增量速度进行平均,加到原物体的速度V上。

到了这一步,我们的检测还没有结束,因为这些计算出来的速度之间有可能互相抵消了,致使个体有可能飞向障碍物,所以到最后,我们还需要再做一次障碍物检测。但对所有的个体都进行过检测以后,我们再将所有的变化应用到数组V[]上,然后再把速度的变化应用到个体的位移和自身的旋转上。来自:https://blog.csdn.net/qq_27880427/article/details/72771329

Unity AI系列

原文链接

著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引

游戏学院公众号二维码
腾讯游戏学院
微信公众号

提供更专业的游戏知识学习平台