浅谈层次化的AI架构

记得在以前的一篇文章中谈到了一种类似于双缓冲的AI结构,最近在整理一些东西的时候,发现这样的AI结构具有一定的通用性,而且层与层之间耦合度相对较低,作为一种层次化的AI架构,非常值得一谈。

在我的脑海中,AI一般分为两个部分,一个是决策(Decision)部分,一个是行为(Behavior)部分,决策部分负责做什么,行为部分负责怎么做。在一些国外的公司里,AI程序员也大致分为这两种(不过,一些国内的企业可能就分的没有这么细,一般都是统称为AI程序员,或者有的分的更粗,将一些游戏中的其他游戏逻辑部分一起涵盖,统称为游戏性(Gameplay,GPP)程序员)。正因为这样,所以我们一般希望,在AI架构上,这两个部分的耦合度是相对较低的,这样也便于任务的分工。所谓层次化的AI架构(Layered AI Architeture)也就基于了这样的理念。看下面这个图:

layered-ai-architecture-1

在这样一个层次化的AI框图中,我们定义了“请求(Request)”这样一个概念,请求可以看作是AI决策的结果,或者称之为一个命令,比如,在射击游戏中,请求可能就定义为,射击,移动,逃跑等等,在动作游戏中,请求就会定义成攻击,格挡,跳跃等等。当行为层收到上层的请求后,就会设法去处理该请求的内容,还是以射击游戏为例,当行为层收到射击的指令,就会从射击的动画列表中选择某个射击动画,然后转向目标,播放动画等等工作来处理射击的请求。所以请求相当于就成了决策层和行为层之间的接口。这样,对于决策层和行为层的输入和输出就很明确了:

  • 决策层:输入(游戏世界信息),输出(请求)
  • 行为层:输入(请求),输出(修改游戏世界的相关信息)

layered-ai-architecture-2

由于有请求层作为中间接口层,所以决策和行为部分就很自然的分开了,而且有清晰的输入和输出,AI团队中的人员的工作职责也就很明确了,做为决策层的AI程序员,就只需要关心如何产生请求,而行为层的AI程序员,只需要关心如何处理请求,一旦定义好完备的请求内容,不管在代码还是在工作上都不会产生很大的粘连度了。

另外值得注意的是,这边的请求层用到了类似双缓冲的结构,分成后端和前端,换个词的话,可以说成当前在处理的请求(前端),和下一个要处理的请求(后端),具体的分析可以参考我以前的文章在AI结构中用双缓冲》,这里就不多做介绍了。

这样的层次化结构在AI中有很强的通用性,因为这是用最高的层面来总览AI的架构,而像其他诸如行为树(Behavior Tree),分层状态机(HFSM)等都可以看成是在决策或者行为层中的具体实现方式。所以不管AI代码是如何实现,大部分都可以归到这种层次化的结构中,因此,我想,我们在设计AI结构之初,就可以用这样的方式来思考和架构整个框架,分割决策和行为,定义请求,然后再针对每一层来选择具体的实现方法。

————————————————————————
作者:Finney
Blog:AI分享站(http://www.aisharing.com/)
Email:finneytang@gmail.com
本文欢迎转载和引用,请保留本说明并注明出处
————————————————————————

(已被阅读19,117次)

20 评论

  1. 您好,首先非常感谢您的分享,也看了双缓冲那篇文章,关于请求层的双缓冲的前端(当前正在处理的请求)和后端(下一次要处理的请求)是否可以理解为前端请求就是上一次行为层从请求层获取到的请求可能现在还处于执行中,也可能其实已经执行完了,只是还没有进行缓冲区的交换?

    1. 《核心游戏系统架构设计》这篇已经给出了解释,因为是从最开始一篇篇看的,看到评论去看了下,理解了。

  2. 博主您好
    看了这篇文章,我产生了一个问题,不限制于AI方面,大概是这样
    如果说决策层的输入时游戏世界的信息,输出是请求,行为层的输入是请求,输出是对游戏世界信息的修改,那运行一次完整的决策和行为层的逻辑就可以看做是一帧,我对游戏世界的帧的理解是:帧是游戏世界的执行单元,帧的执行结果是对游戏世界的更改,那么每一帧都可以看做是以上一帧对游戏世界的输出作为输入,以这个输入来进行一些操作,得到了一些结果,用来作为输出来供下一帧使用。
    如果这样来理解的话,那么就产生了一个问题:每一帧中各个对象直接的运算和操作从逻辑上来说都是并行的,他们都是以上一帧的输出来作为运算依据,但是由于,我们是使用串行编程的方式来模拟并行的游戏逻辑,比如时候一个容器来储存游戏对象,然后使用循环来遍历容器并执行对象的操作,那这样的方式难免会产生处于容器前部的对象修改了游戏世界的信息(比如自身信息,血量位置等等),然后处于容器后部的对象却依赖于容器前部对象的数据来执行一些操作,那这样造成的实际结果就是,容器前部的对象依赖于上一帧的输出,容器后部的对象依赖的却可能是当前帧的输出。
    总结一下就是,每一帧中的对象的操作所产生的结果,是否应该再对当前帧中其他的对象有影响呢?如果不能,那么怎么去避免容器遍历过程中,不同对象对同一个数据的读写冲突呢?
    – -感觉这个不是游戏AI方面的问题,毕竟按照文中所说,决策层产生的输出是请求,请求本身是不会游戏世界产生影响的,实际产生影响的是行为层,但是如果决策层产生的请求,行为层来执行的结果也是对同一个变量来做修改的,或者不同对象有读写冲突的话,要怎么解决呢?
    不好意思会问这样的问题,见谅- –

    1. 你可以看一下《核心游戏系统架构设计》,里面的讨论更详细,你说的这个问题或多或少存在,但是一般来说,不太会产生太大的影响,也可以有一些方案,比如像我在《核心游戏系统架构设计》里说的,先抽象出信息层,保存可能会影响的世界信息,还有一个就是不是一个对象一下子tick完,游戏基本上都是采用分层tick,也就是,而是大家一起先tick AI,再tick行为,再tick动画,再tick物理等等

  3. 您好,非常高兴今天看到了您的博客,让我学到很多东西,非常感谢。

    关于这一篇的内容我想问问,产生的“请求”应该是一个什么样的粒度呢?比如用户输入一个命令为使用技能,而使用这个技能可能需要两个动作,1.移动到合适位置 2.释放技能。决策层应该是先发送移动请求,再发送释放技能的请求吗?

    1. 确实,粒度是需要不断的调整的,如果是你说的这个例子,决策层一般就是发,我要释放技能A,然后行为层就用一个序列节点来完成这个决策

  4. 你好,首先要特别感谢你提供的文章,每一篇看都我都是提壶灌顶的状态,真是感谢。

    看到这一篇的时候,我想问一下,你说决策层是做什么,行为层怎么做,那么谁是监督?比如决策移动到A点,我在那里确定行为层做完了呢?还是在决策层里做检查?一个移动也许花2分钟才能完成,那么决策层是否在一停的发送请救让行为层对A点移动呢,我好像有点混乱,不知道是否表达请楚

    1. 你好啊,行为层在完成一项任务的时候,会给决策层一个报告,告诉它我完成了。就用你的那个例子来说,比如决策层说要移动到A点,然后行为层就开始执行这个任务,比如他有一个MoveTo的方法去执行这个决策,在MoveTo里面会检测和处理是否到达A点,当到达了就向决策层报告我完成了,然后执行下一个任务(或者没有任务就进入空闲)。当然在移动过程中,决策层可能会产生一个新的任务要做,比如攻击,这样行为层就会打断MoveTo,去执行这个新的任务。当然哪个任务可以被打断,哪个不能被打断是取决于游戏的设计。决策层产生任务的方式,也是取决于游戏的需求。

    2. 博主说的这种情况是否是client做AI 自己消化掉;如果是cs模式,完全不需要报告,如果要打断也是以消息驱动的模式来做,个人理解,请指正。

    3. Finney :你好啊,行为层在完成一项任务的时候,会给决策层一个报告,告诉它我完成了。就用你的那个例子来说,比如决策层说要移动到A点,然后行为层就开始执行这个任务,比如他有一个MoveTo的方法去执行这个决策,在MoveTo里面会检测和处理是否到达A点,当到达了就向决策层报告我完成了,然后执行下一个任务(或者没有任务就进入空闲)。当然在移动过程中,决策层可能会产生一个新的任务要做,比如攻击,这样行为层就会打断MoveTo,去执行这个新的任务。当然哪个任务可以被打断,哪个不能被打断是取决于游戏的设计。决策层产生任务的方式,也是取决于游戏的需求。

      这里行为层完成之后会报告给决策层,感觉像行为树的处理方式:子节点处理结果会返回给父节点。 但根据前面的描述,决策层和行为层中间是通过请求层来连接的,当然可以用行为树来实现决策层和行为层。我的疑问是:怎么把行为层反馈给决策层? 可以通过行为树来实现的么?

    4. 行为层的反馈不是直接向上走的,可以通过改变一些游戏世界状态,或者记录在单个实体上的某些状态来实现,等到下一帧的时候,决策层再通过这些改变过的状态来继续往下走。可以看我最新的一片文章《核心游戏系统架构设计》,里面说到了,在决策层之前,会有一个信息层,就是用来抽象和获取新的游戏世界的数据,并给后面的决策来使用的。当然,真正实现的时候,可以根据情况来灵活选择,是用标记,还是黑板,或者是各种数据类等等

  5. Hi,我又来了,您这里的BT相关文章,每一篇都读了至少三遍,但是由于没有真正去实现过,所以理解的还不是很到位。
    现在有一个问题不知道这么理解对不对,NPC需要有自己的决策层和行为层,而玩家本身只需要有行为层,因为玩家的输入就是决策层,这样理解对吗?
    如果对的话……那请求层又可以理解为哪一部分呢。

    1. 呵。谢谢捧场~。你的理解很对的,玩家的输入就是玩家的决策,所以和AI的决策一起都放在决策层里面,请求层是决策和行为的接口,我们可以定义很多很多的请求,这些请求都是决策的结果,比如,我想要“移动”,“射击”或者“跳跃”等等,这样的话,对于行为层来说,它只看到这些请求,而不需要去管这些请求是由AI发出的,还是玩家发出的。所以在这个层次化的结构中,就是通过定义这些请求,将决策和行为分开的

  6. 哦哦~ 又看了一遍,层次状态机就是文章中所说的框架的一种实现方式。那麻烦可否具体解释一下,“HFSM”和“决策行为”的对应关系……

  7. 您好。
    看了一遍没怎么看懂,就又看了一遍。
    我没有接触过非常复杂的AI,指写过简单的FSM,对于文章中说的内容,觉得自己写过的状态机有所联系,但是又对应不起来,在这问个问题,您是否使用过“层次状态机”?就是状态中包含状态的,我接触过这种层次状态机,但是和文章中说的框架联系不起来
    看了几篇行为树的文章,层次状态机和行为树的关系也比较混沌……望指点。

    1. 这个是一个游戏AI逻辑的最大的框架,具体决策层和行为层用什么技术来实现,是状态机还是行为树,或者其他的技术都是可以的,这个层次化的结构主要就是将游戏中的AI分成了两个部分,就像我说的“做什么”和“怎么做”,比如AI决策出要移动到A点,这个属于决策层的部分,然后行为层负责怎么去移动到A点,比如要播放哪个动画等等,这个层次话结构,就是把这两个部分分开了。

发表评论

邮箱地址不会被公开。

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据

Copyright © 2011-2020 AI分享站    登录