最近在路上一直在思考AI中的懒惰问题,为什么会突然想到这个,实在是因为这个问题十分常见,它非常简单,但是又非常难以漂亮的解决。先从一个问题引入吧。看下面这张图
假设我们有一个开阔的战场,这个战场被划分成了4个小区域,A~D来表示,实心小红圈表示进攻方,也是我们控制的人。实心小蓝圈表示防守方,是电脑AI控制的人。防守方为了不让进攻方突破,它有一个很简单的AI算法,当进攻方在A的时候,防守方就跑到C区域的中心(空心圈表示),当在B的时候,防守方就跑到D区域的中心(空心圈表示)。
这个算法看似很完美,但看下面一张图
当我们控制小红圈在A和B的边界快速来回移动的时候,试想一下蓝圈的行为,它就会不停在两个目标点转换,如果是带朝向的真实物体,就会发现,蓝圈一直在做180度的大转身,显得非常的傻。这就是AI程序中经常碰到的边界问题,也就是,当判断条件出现边界值的话,在边界附近会出现行为抖动的现象。解决边界问题的一个主要方法就是为AI引入“懒惰”的机制。
所谓“懒惰”,就是通过人为的为AI加入延迟机制,来使AI的行为更为真实。在这里,我们就需要调整我们的算法,既然觉得AI太快,我们就让他慢一点,加入一个计时器,这是非常直观的一种解决方案,我称之为计时器法。描述如下:
当蓝圈根据红圈位置得到一个新的目标点时,我们设定计时器为n秒,这样表示,n秒内目标点不允许被变更,然后计时器开始倒计时,当计时器倒计时结束时,我们再为蓝圈得到一个新的目标点,再次设定计时器,依次类推。
这样当我们在边界点快速移动的时候,蓝圈就不会随之快速的改变目标点了,相当于变得懒惰了,这种做法很简单。在AI中,计时器一直是一个好东西,有时我们不需要AI决策的太频繁,一方面为了真实,一方面也为了优化,这样我们就可以用计时器来控制AI决策的频度。引申一点说,这里设定延迟n,可以每次是一个随机值,随机值的好处就是,当有很多AI需要同时决策的时候,可以避免AI在一帧里集中计算,而其他帧空闲,造成AI决策的峰值。
还有一种Lazy的方法,我称之为交叉边界法,看下面这张图
我们为每个区域创建一个虚拟的区域,图中用粉框表示,虚拟区域比原来的区域要大一圈,这就使得A,B的虚拟区域的边界有一部分是重叠的。我们新的算法描述如下:
当红圈在A区域,并且不在B的虚拟区域中时,蓝圈的目标点在C的中心
当红圈在B区域,并且不在A的虚拟区域中时,蓝圈的目标点在D的中心
比较一下原来的算法,多了两个额外的条件,由于虚拟区域的存在,使得边界处不再是,A和B的二元差别,而是变成了A,A&B,B三个值,这样边界的跳变也就被平滑掉了,这种是专为解决边界问题而引入的Lazy机制,它会在边界处存在一定的决策延迟。
针对这个问题,使用上述的算法,会存在一个问题,如下图:
当红圈从A区域移动到图示中新位置的时候,由于虚拟区域的存在,蓝圈不会移动到D的中心,这会使得此处的AI行为不符合我们的预期。一个改进的做法是……..,下次公布一下我的想法,留给大家可以思考一下。:)
这两种就是非常常用的使AI懒惰的方法,它们有一些很好的优点,简单,易于实现。但却存在的一个致命的问题,就是需要修改原本的AI代码,而且这两种方法都会使得代码比较丑陋,不宜维护。我一直在想,有没有一个比较通用的解决方案或者代码片段,使得这样的问题得到解决,而不用修改原有的AI算法。欢迎大家留言和我讨论。
————————————————————————
作者:Finney
Blog:AI分享站(http://www.aisharing.com/)
Email:finneytang@gmail.com
本文欢迎转载和引用,请保留本说明并注明出处
————————————————————————
如果是针对区域的策略 就可以有不同的实现啊 代码也不会丑陋吧
区域会丑陋,有洁癖和强迫证的有时很很纠结
评论测试,欢迎大家光临
加一个队列缓存,连续多帧的趋势,总和与一个阀值对比也能解决这种临界问题