目前常见的AI模型包括FSM(有限状态机)和Behavior Tree(行为树)两大类。
一、FSM(有限状态机)
相对于switch-case来说,FSM编程与人类思维相似从而便于梳理,更加灵活。当每种状态被封装之后,就不会再有一个“*”函数来控制所有的逻辑,每个状态只要管好它自己就好了。这样复杂的决策系统就被切分两个子系统,不同状态以及状态之间的转化。切分后的这两个子系统的复杂度与原系统比都大大简化,从而使得代码变得可以维护。FSM在相当多的游戏中被应用,甚至Unreal Engine的脚本语言是直接支持状态编程的。
当游戏中的NPC决策并不太复杂时候,FSM是非常有效的。比如Half-Life这款游戏,里面的AI被业界称赞了很久,而其中的AI就是通过FSM来实现的。
我们接下来通过一个简单的例子来认识一下FSM。
比如一个AI文字表述如下:
1、平时的状态是巡逻
2、如果遇到敌人之后打量一下敌人
3、如果敌人比自己弱小,那就打攻击
4、如果敌人比自己强大,那就跑逃跑
那么这个可以很自然的转换成FSM,然后进行编程实现
带边框的节点表示状态,而箭头上的条件表示状态切换的条件。
虽然FSM简洁,和人的直觉思维相近,但是FSM也是有缺点的:
A、由于我们所能做的仅是编辑从一状态到另一状态的转换,而无法做出更高层次的模式功能,所以会导致我们发现自己总是在构建相似的行为,这会花费我们大部分时间。
B、使用 FSM 实现目标导向的行为需要做很多工作。这是一个大问题,因为大部分有针对性的AI 需要处理长远目标。
C、FSM 难以并发。当并行运行多个状态机,要么死锁,要么我们通过手工编辑来确保它们在某个程度上能够兼容。
D、大规模支持较差,即使是分层的有限状态机,也难以大规模扩展。它们往往是在其中夹杂一大块逻辑代码,而非行为编辑模块化。
E、用 FSM 实现任何设计都需要做大量工作,需要花费设计师的大量时间(并非编程时间),甚至最终这还会成行为中的 bugs 的来源。
行为树是在Next-Gen AI中提出的模型,虽说是Next-Gen AI,但距其原型提出已有约10年时间。其中Spore(孢子),Crysis(孤岛危机)2,Red Dead Redemption(荒野大镖客:救赎)等就是用行为树作为它们的AI模型。而越来越多的引擎也都开始直接支持行为树,比如Cry Engine, Havok等。
对于用行为树定模型构造的AI系统来说,每次执行AI时 ,系统都会从根节点遍历整个树,父节点执行子节点,子节点执行完后将结果返回父节点,然后父节点根据子节点的结果来决定接下来怎么做。
行为树常见的基本类型节点有5种(当然也可以扩展更多类型):
1、顺序节点(Sequence):属于组合节点,顺序执行子节点,只要碰到一个子节点返回false,则停止继续执行,并返回false,否则返回true,类似于程序中的逻辑与。
2、选择节点(Selector):属于组合节点,顺序执行子节点,只要碰到一个子节点返回true,则停止继续执行,并返回true,否则返回false,类似于程序中的逻辑或。
3、平行节点(Parallel Node):提供了平行的概念,无论子节点返回值是什么都会遍历所有子节点。所以不需要像Selector/Sequence那样预判哪个Child Node应摆前,哪个应摆后。Parallel Node增加方便性的同时,也增加实现和维护复杂度。
4、条件节点(Condition):属于叶子节点,判断条件是否成立。
5、执行节点(Action):属于叶子节点,执行动作,一般返回true。
接下来我们看一个行为树构造的AI,这个AI的逻辑文字表述为,一个NPC在晚上需要执行巡逻任务。而且如果天下雨的话,户外的人是需要打伞的。
程序大概流程如下
1、先处理Basic_AI节点,由于该节点是并行节点,所以将会依次处理接下来两个子树,无论第一个子树的返回值是什么。
2、对于”打伞”节点,由于该节点是顺序节点,所以会依次处理其子节点,但是如果某个子节点返回false,那么该节点执行停止执行,并且返回false。因此执行打伞动作会不会执行取决于在它前面的两个条件是否返回true
3、执行完”大伞”节点后,接下来必然会执行守夜节点,而守夜节点是选择节点,所以要么会执行夜里巡逻,要么会执行休息节点。夜里巡逻会不会这姓自然取决于条件节点”是晚上吗”的返回值
行为树模型看似简单,但是以下几个优点让行为树目前变成了复杂AI的主流模型
A、静态性
越复杂的功能越需要简单的基础,否则最后连自己都玩不过来。即使系统需要某些”动态”性,也应该尽量使用静态的行为树来表示。Halo3相对于Halo2对BT AI的一个改进就是去除了一些的动态性。原则就是保持全部Node静态,只是根据事件和环境来检查是否启用Node。
静态性直接带来的好处就是整棵树的规划无需再运行时动态调整,大大方便设计人员和编程人员,并且大大减少诡异的bug,同时这也为很多优化和预编辑都带来方便。
B、直观性
行为树可以方便地把复杂的AI知识条目组织得非常直观。
默认的组合节点处理子节点的迭代方式就像是处理一个预设优先策略队列,也非常符合人类的正常思考模式:先最优再次优。
此外,行为树编辑器对优秀的程序员来说也是唾手可得。
C、复用性
各种节点,包括叶子节点,可复用性都极高。
D、扩展性
可以容易地为项目量身定做新的组合节点或修饰节点。还可以积累一个项目相关的节点库,长远来说非常有价值。
在浏览过行为树和有限状态机之后,大家很自然可以根据项目来选择所用的模型。对于AI并不是太复杂的项目来说,选择有限状态机是很理智的行为,特别是在有些引擎支持的情况下。但是如果NPC的状态非常多,成千上万种,那么行为树就可能是避免项目最后崩溃的好办法。