人工智能AI------有限状态机、分层状态机、行为树
https://www.cnblogs.com/zhanlang96/p/4793511.html
人工智能遵循着:感知->思考->行动
决策方法:有限状态机(Finite-State Machines),分层状态机(Hierarchical Finite-State Machines),行为树(Behavior Trees),效用系统(Utility Systems),目标导向型行动计划(Goal-Oriented Action Planners),分层任务网络(Hierarchical Task Networks)
有限状态机
有限状态机是目前游戏AI中最常见的行为模型。状态机的代码简单又快速,使用上强大、灵活、计算开销小。
状态机的一个好处是可以可视化,如下图所示:
图中有四个状态:巡逻(patrol),查看(investigate),攻击(attack),逃走(flee),我们把实心圆当做初始状态。
简要过程:假设NPC士兵正在保卫他的阵地,当前状态为巡逻,当他听到什么动静时就会转到查看状态,跑到声音源去查看,如果看到敌人就转到攻击状态,如果没看到过一段时间又会回到巡逻状态。在攻击状态中如果血值低下就会进入逃跑状态。如果击败了敌人,又会回到巡逻状态。
状 态机状态类的一个主要结构如下,onEnter函数就相当于unity中的Start()函数,在类开始时调用,作为对旧状态的过度和新状态产生的开始, 比如当从巡逻转向攻击状态时,可以在攻击状态的开始让NPC大喊“发现敌人!进攻!”等等。onUpdate()就相当于unity中的 Update(),你可以让它每帧都执行,或者几秒钟执行一次,是循环执行的,每次执行时间间隔由你来决定。onExit()就是在退出一个状态之前要执 行的,比如,杀死敌人之后由攻击状态转向巡逻状态之前,让NPC做一个欢呼手势并大叫胜利了。FSMTransition列表为将要转到的所有可能的状 态。
class FSMState
{
virtual void onEnter();
virtual void onUpdate();
virtual void onExit();
list<FSMTransition> transitions;
};
每个状态还存储着FSMTransition的类,代表能从当前状态可以转到的状态
class FSMTransition
{
virtual bool isValid();
virtual FSMState* getNextState();
virtual void onTransition();
}
当转换条件满足时isValid()返回true,比如当发现敌人NPC就从巡逻状态转到攻击,getNextState()返回将要转到的状态,onTransition()是状态之间转换的过渡,和上面说的onEnter()差不多。
最后是有限状态机类FiniteStateMachine
class FiniteStateMachine
{
void update();
list<FSMState> states;
FSMState* initialState;
FSMState* activeState;
}
有限状态机类包含一个包含所有状态的列表states,initialState为初始状态,activeState为当前状态。
伪代码如下:
在 activeState.transtitions中循环调用isValid(),检测是否符合达到下一状态的条件
如果符合转换条件
调用activeState.on Exit(),退出当前状态
设置activeState 为 validTransition.getNextState(),把当前状态赋值为下一状态
调用activeState.onEnter(),下一状态的开始
如果不符合转换条件,调用activeState.onUpdate(),让NPC执行当前状态需要做的事
在编写有限状态机的代码只前最好画一个上面的草图,这样既可以明确转换关系,又可以不漏掉该有的状态。
分层有限状态机
有限状态机虽然好,但是它有很大的缺点,当状态少的时候可以运用自如,当状态多的时候10个以上就已经结构非常复杂,而且容易出错。
如果我们让NPC巡逻两个地方,比如安全的室内,和门口
如 果我们想在一个状态上附加一些状况,例如当NPC在巡逻时,让他接一个电话然后再恢复巡逻,此时如果使用有限状态机的话我们必须要新建一个打电话的状态来 做过渡,但是此时的巡逻有两个,所以能接到电话的状态也有两个,然后加了两个相同的状态,很多这样的重复的小状态使得状态机越来越复杂。如下图
这时,我们可以用分层有限状态机来解决这个问题,把多个状态机归为一层,如下图,把巡逻安全处和门口归为看守建筑,这样我们只需要有一个打电话状态就可以了。
分 层有限状态机增加了一个滞后,在有限状态机中并没有,在一个普通的有限状态机中,是从初始状态开始的,在分层有限状态机中是一个嵌套的状态。注意上图有H 的圈,代表历史状态(history state),当我们第一次进入嵌套状态->看守建筑时,历史状态H表示为初始状态,之后历史状态H表示为最近处在的一个状态。
在我们的例 子中:初始状态就是看守建筑,,然后进入看到手机按住这个嵌套,巡逻安全处是初始状态。当从巡逻安全处转换到巡逻门口这个状态时,H历史状态就转变为巡逻 门口状态,此时来电话了,转换到接电话状态,接电话结束,我们回到嵌套状态中的历史状态,此时为巡逻门口,可见H历史状态就是一个临时的,便于嵌套外的状 态返回到之前的嵌套内的小状态,以不至于出错,或者换回了别的状态,如果接完电话回到巡逻安全处,那就出大错了。
分层有限状态机,就这样避免了重复状态,可以实现更大的更复杂的状态。
实例:
Halo2使用了这一技术,如下图
可见:把使用手雷、掩蔽、防御归为自卫,交战部分使用了多层嵌套,但是原理是一样的,向尸体设计和搜查尸体归为战后处理。在撤退和闲置部分只有一个行为被嵌套,但是日后可以继续添加行为,可扩展性良好。
至于如何在嵌套的层里对行为进行选择,可以就按这个顺序执行,也可以加上权重优先级,或者你想让他执行哪个通过代码来控制。
行为树
行为树是树型结构的,每个节点都代表了一个行为,每个行为都可以有子行为。
所有行为都有一个先决条件,就是产生的这些行为的条件。
整 个算法先从树的根部开始,然后开始检查每一个先决条件。树的每一层只可以执行一个行为,所以当一个行为正在执行,它的兄弟节点都不会被检查,但是它们的子 节点还是要检查的。相反如果一个行为的先决条件当前并不满足,则跳过判断它的子节点,继续判断它的兄弟节点。一个树全部检查完毕之后,决定执行优先级最大 的,然后再依次执行每个动作。
伪代码:
使根节点为当前节点
当存在当前节点
判断当前节点的先决条件
如果先决条件返回true
把节点加到执行清单
使子节点为当前节点
否则
使兄弟节点为当前节点
执行执行清单上的所有行为
不同于状态机,行为树是无状态的,不需要记下之前执行的行为,只是判断行为该不该执行。
行为树的节点之间是不相关的,删除或增加节点,对其他节点都无影响。所以,可扩展性也是行为树的一个优势。另外还可以为决策树添加灵活性与随机性,父节点可以随机决定是否检查子节点。
缺点:决策树做的选择并不一定是最优的,结果也不一定是我们想要的。而且决策每次都要从根部往下判断选择行为节点,比状态机要耗费时间。每次决策都要经过大量的条件判断语句,会变得非常慢。
另外还有一个问题,例如:一个农民要收割作物,敌人出现了,农民逃跑,逃出了距离敌人的一定范围之后,又回去收割作物,走到敌人的范围又逃出,这样来回往复,是一个弊端,,可以根据情况来写代码避免,否则会被玩家***的。
效用系统
人工智能的逻辑->电脑的逻辑,是基于简单的bool问题,比如:“我能看到敌人吗?”,“我有弹药吗”,是简单的是或者不是的问题,所以做出的行为通常是极端化的,一个单一的行动。比如:
if (CanSeeEnemy())
{
AttackEnemy();
}
if (OutOfAmmo())
{
Reload();
}
即时有多条件的行为,bool判断带来的也是一个单一的行动。
if (OutOfAmmo() && CanSeeEnemy())
{
Hide();
}
所 以有些情况,只是做这些布尔判断是不合适的,会遗漏很多情况,判断也不妥当。比如:我们可能需要同时考虑与敌人的距离、有多少弹药、饥饿程度、HP值,等 等。这些判断条件能映射出许多动作,比我们单一的判断做不做这个动作要好很多。utility-based system,基于效用的系统,会根据权重、比率、队列和许多需要考虑的事项来做出最优选择,使AI比普通的行为树更有头脑。根据上面的例子,使用效用系 统我们的AI可以做出我们想要的动作,并根据当前情况做出不同强度的动作,使AI真实、更具可能性,也不再是只有一个正确的选择了。决策树就是对AI说, “只是你将要做的一个行为”,效用系统就是对AI说:“这些是你可能要做的行为”
Sims模拟人生的人工智能就是使用的效用系统(sims的人工 智能让我膜拜至今),在sims中,小人结合当前环境和自身的状态,来做出行动的选择。例如:小人“非常饿”结合环境“没有食物”会比只有“有一点饿”更 加吸引人的眼球。如果“有一点饿”小人会以接近“美食”为第一执行行为。注意,这里的“美食(的美味程度)”、“食物很少(食物储备程度)”、“一点饿 (饿的程度)”,都是一个有范围的数值(常用的是0-1的浮点值)。
当需要选择新的行为时,我们通过分数(上面说的各种程度)来选择相对最优的选择,或者加上一个随机值再选择,使得接近优选的几个选择都有一定几率(几率可根据所加随机值决定)被选中。
目标导向型行动计划
GOAP 来源于STRIPS方法,这两种都是让AI创造他们自己的方法去解决问题,我们提供给它一系列可能的动作作为对这个世界的描述,和每个动作使用的先决条 件,和行动带来的影响。AI拥有一个初始状态和他需要达到的目标。有一组目标,AI可以通过优先级或当前状态选择一个。计划系统决定一个动作序列来满足当 前目标,计划出一个像路径一样的能最简单达到目标状态的动作序列。
GOAP是一个反向链接搜索,从要实现的目标开始,找到什么动作能实现目标,在寻找刚才动作的先决条件,一直往前推,知道达到你的当前(初始)状态。这种反向链接搜索替代了启发式的前向链接搜索。
伪代码:
把目标加到未解决事件列表
对于每个为解决事件(for)
移除这个为解决事件
找到达成事件的动作
如果动作的先决条件已经满足
增加动作到计划中
往回推需要达到先决条件的动作到计划中
否则
添加该先决条件到未解决时间中
例 如:我们建立一个NPC士兵,把它的目标设为杀死其他敌人,我们设置它的目标为Target.Dead。为了让目标去死,NPC必须要有一个武器用来射 击,这是一个先决条件,但是现在NPC并没有正在装备的武器,NPC就需要执行找到武器这个动作,如果NPC有武器库,他就会从武器库中拿一个,如果病没 有武器库,就需要寻路去找一个武器装备了。得到武器装备之后就要找到敌人,实现方式多种多样,徒步寻找、或者NPC周围有车也可以开着车去寻找。我么发 现,我们给NPC大量的动作选择,让NPC自己决定该做什么,因而产生动态不可预知又有趣的行为,而且表现得很自然,比开发者创建行为好多了。
这里有一个简单的例子:http://gamerboom.com/archives/83622
分层任务网络
HTN 也是寻找一个计划来让AI执行,不同之处在于怎样找出这个计划。开始拥有一个初始状态和一个跟任务代表我们需要解决的问题。原理是最高级的任务分解成更小 的任务再继续分解直到我们解决问题。每个高级任务都有很多方式被完成,当前世界状态决定高级任务要分解成哪组小任务。HTN与GOAP相反,HTN是前向 链接搜索,是从当前状态一直推到目标状态,向前推直到问题解决。世界状态分散成几种属性,它的HP、精力,敌人的HP、相距距离,计划根据这些来制定。
我 们有两种任务:原始任务和复合任务。原始任务是可以只解决问题的任务,也就是可以直接达到目标的任务。在游戏中,它可以为开火、装填子弹、移动到掩蔽物。 这些人物可以影响世界状态,开火这个任务需要先有子弹,并执行装填子弹这个任务。复合任务是高级别的任务,可以看作方法。一个方法是一组任务可以完成复合 任务,这一组任务是由先决条件决定的。复合任务让HTN推断出世界并且决定该做什么动作。
使用复合任务,我们就能构建一个HTN域,这个域是一大层任务,代表我们解决问题的方法。
伪代码:
增加根复合任务到分解列表中
对于每个在我们分解列表中的任务(for)
移除任务
如果任务是复合任务
找到满足当前条件状态并且能处理该复合任务的方法
如果该方法找到了,增加方法的任务到分解列表中
如果没找到,恢复到之前分解任务的状态中
如果任务是原始任务
在当前状态下执行任务
增加任务到最终计划列表
HTN就是从最高级的根任务分解更小的任务再分解成更更小,分解是需要判断当前状态和条件的。当我们终于分解为原始任务,我们把原始任务加到最终计划中,每一个原始任务都是一个可操作步骤,我们可以直接执行它。
Unity AI planner: https://www.bilibili.com/video/av67436639
人工智能AI------有限状态机、分层状态机、行为树的更多相关文章
- FSM(状态机)、HFSM(分层状态机)、BT(行为树)的区别
游戏人工智能AI中最常听见的就是这三个词拉: FSM 这个不用说拉,百度一大堆解释, 简单将就是将游戏AI行为分为一个一个的状态,状态与状态之间的过渡通过事件的触发来形成. 比如士兵的行为有“巡逻”, ...
- AI逻辑实现-取舍行为树还是状态机
AI逻辑实现-选择行为树还是状态机? 关注AI的朋友可能会看过赖勇浩翻译的<有限状态机时代终结的10大理由> ,里面谈到了状态机的诸多弊端.同时在ppt(附上下载地址)中述说了行为树的诸多 ...
- 数据挖掘(data mining),机器学习(machine learning),和人工智能(AI)的区别是什么? 数据科学(data science)和商业分析(business analytics)之间有什么关系?
本来我以为不需要解释这个问题的,到底数据挖掘(data mining),机器学习(machine learning),和人工智能(AI)有什么区别,但是前几天因为有个学弟问我,我想了想发现我竟然也回答 ...
- 【转】人工智能(AI)资料大全
这里收集的是关于人工智能(AI)的教程.书籍.视频演讲和论文. 欢迎提供更多的信息. 在线教程 麻省理工学院人工智能视频教程 – 麻省理工人工智能课程 人工智能入门 – 人工智能基础学习.Peter ...
- 人工智能--AI篇
AI背景 在当今互联网信息高速发展的大背景下,人工智能(AI)已经开始走进了千家万户,逐渐和我们的生活接轨,那具体什么是AI呢? 什么是人工智能(AI)? 人工智能:简单理解就是由人制造出来的,有一定 ...
- 解读 --- 基于微软企业商务应用平台 (Microsoft Dynamics 365) 之上的人工智能 (AI) 解决方案
9月25日微软今年一年一度的Ignite 2017在佛罗里达州奥兰多市还是如期开幕了.为啥这么说?因为9月初五级飓风厄玛(Hurricane Irma) 在佛罗里达州登陆,在当地造成了挺大的麻烦.在这 ...
- 人工智能AI芯片与Maker创意接轨(下)
继「人工智能AI芯片与Maker创意接轨」的(上)篇中,认识了人工智能.深度学习,以及深度学习技术的应用,以及(中)篇对市面上AI芯片的类型及解决方案现况做了完整剖析后,系列文到了最后一篇,将带领各位 ...
- 人工智能AI芯片与Maker创意接轨 (中)
在人工智能AI芯片与Maker创意接轨(上)这篇文章中,介绍人工智能与深度学习,以及深度学习技术的应用,了解内部真实的作业原理,让我们能够跟上这波AI新浪潮.系列文来到了中篇,将详细介绍目前市面上的各 ...
- 国家制定人工智能(AI)发展战略的决策根据
在今年两会上,李彦宏的提案有何道理?提案的依据是什么?这个问题必须说清楚,对社会公众有个交代. 回想过去,早在上世纪九十年代,用"电子网络"模拟人脑的想法已经出现.这样的" ...
随机推荐
- C语言/C++知识
<C与指针>pdf 下载: 新浪微盘: https://vdisk.weibo.com/s/A6gkKkHrGH0g
- 【CF160E】Buses and People
题目大意:给定 N 个三元组 (a,b,c),现有 M 个询问,每个询问给定一个三元组 (a',b',c'),求满足 a<a', b'<b, c'<c 的最小 c 对应的元组编号. ...
- VCL界面开发必备装备!DevExpress VCL v19.1.5你值得拥有
DevExpress VCL Controls是 Devexpress公司旗下最老牌的用户界面套包.所包含的控件有:数据录入,图表,数据分析,导航,布局,网格,日程管理,样式,打印和工作流等,让您快速 ...
- 弹出框 popover.js
弹出框 popover.js 为任意元素添加一小块浮层,就像 iPad 上一样,用于存放非主要信息. 弹出框的标题和内容的长度都是零的话将永远不会被显示出来. 插件依赖 弹出框依赖 工具提示插件 ,因 ...
- VM删除快照失败,磁盘空间不足,只是删除了快照名字(全网唯一解决办法)
原创: 删除之前的快照,发现只是把名字删除了, 看着这么多文件也不知道怎么删,一顿百度google也是没找到答案 于是就自己琢磨 因为删除快照的时候,是先把快照删除,然后删除无效的文件 所以先让这个盘 ...
- python 数据库错误处理
DB API中定义了一些数据库操作的错误及异常,下表列出了这些错误和异常: 异常 描述 Warning 当有严重警告时触发,例如插入数据是被截断等等.必须是 StandardError 的子类. Er ...
- react 的className动态修改
https://blog.csdn.net/suwyer/article/details/81481507(copy) <div style={{display: (index===this.s ...
- Nowcoder Playing Games ( FWT 优化 DP && 博弈论 && 线性基)
题目链接 题意 : 给出 N 个数.然后问你最多取出多少石子使得在 NIM 博弈中.后手必胜 分析 : Nim 博弈模型,后手必胜当且仅当各个堆的石子的数目的异或和为 0 转化一下.变成最少取多少石 ...
- C语言写数据库(一)
/*** connect.c ***/ #include<stdio.h> #include<stdlib.h> #include"mysql.h" int ...
- 关于MySQL中查询结果的count和from后的条件与where后的条件对比
啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦啦 ...