一.游戏AI
游戏AI(Game AI),是指在游戏中,由已经写定好的程序控制的“类人化玩家”,俗称电脑玩家。一般的游戏AI能够拥有对真实玩家的一系列操作感知的能力并对此作出交互行为,比如:攻击(Attack),逃跑(Run away)等。而且AI所做出的反应并不是凭空生成,而是通过模仿真实玩家的操作使其行为富有“智能化(Intelligent)”。
需要注意的是,一般的游戏AI与我们讨论计算机视觉、自然语言处理等领域时所说的AI(人工智能)并不相同,考虑到游戏的开发成本,周期以及家用计算机处理能力,游戏AI的智能度相对较低。不过随着硬件的发展,游戏AI始终会朝着真正AI的方向发展。
游戏AI中通常分为定性和非定性两种。
- 定性:定性即AI的行为是人为设计好的,只有true(做出反应)或false(不做出反应)。比如说怪物AI,感知到玩家进入视野范围,就会往玩家此时的方位移动,AI不会思考玩家是否携带武器,是否处于某种状态之类的情况。
- 非定性:非定性即AI的行为有一部分是不可预测的,具体实例是让AI角色学习到适应玩家的行为。这样的学习能力可以利用人工智能的神经网络、贝叶斯技术或遗传算法得到。该技术可以让 AI 自主进行学习,并进化出新的行为,增加游戏可玩性。开发者也无需考虑到AI在游戏中所出现的所有情况,可以减少定性AI所产生的一些BUG。目前已经有一些3A开发厂商开始对这一方面进行深入研究。
目前游戏AI基本归结为三个部分的能力:感知,思考,动作。
- 感知:是指能够察觉到周围环境变化,如玩家进入视野,AI受到攻击等。
- 思考:是指能够对感知到的事物进行一个选择反馈,“思考”该做出什么行为,这是AI中最主要的组成部分。
- 动作:是指AI通过思考得出结果并根据该结果在游戏做出实际的行为,攻击,逃跑,交流等都属于这一类。
二.游戏AI的基本实现方式
Ⅰ.朴素AI
朴素AI指的是仅仅使用简单的分支语句(if…else或switch…case)对AI的行为进行判别和分类。
举个栗子,一个敌方士兵在基地站岗,拥有以下几个基本行为:
- 玩家未靠近时自动巡逻
- 玩家靠近基地时(5m)向玩家移动
- 碰见玩家(<2m)就进行攻击
- 血量低于30%时寻找掩体并躲起来
- 血量为0时死亡
IF…ELSE实现:
if(AI.HP == 0){
AI.Dead();
}else if(AI.HP > 0 && AI.HP <= 0.2){
AI.FindBunker();
}else if(AI.Distance - Player.Distance <= 2){
AI.Attack();
}else if(AI.Distance - Player.Distance <= 5){
AI.MoveToPlayer()
}else{
AI.Patrol();
}
由于游戏中有多种AI,每种AI的行为方式不尽相同,用这种方法我们需要为每一种AI单独写一份代码,几乎没有可重用性,会使开发人员的工作量增大。但是因为朴素AI的效率高,代码直观,所以一般用在项目初期的测试以及应急时期。
Ⅱ.AI有限状态机 (Finite-state machine,FSM)
有限状态机是一种抽象机制,通常设定了各种不同的预定状态。有限状态机也可以定义一连串的条件,以便确认何时应该改变状态,当一个事件的发生,将会触发一个动作,或者执行一次状态的迁移。FSM中一定存在两种状态–初始状态和结束状态,在启动一个FSM时,首先必须将FSM置于“起始状态”,然后通过输入一系列操作,最终,FSM会到达“结束状态”或者“消亡状态”。
任何一个FSM都可以用状态转换图来描述。这里我仍然拿上一个栗子来说,下面是一个实际栗子的状态转换图:
简单的FSM代码:
private Enemy enemy = new Enemy();
public void EnemyAction()
{
if(enemy.HP){
status = AI.Dead();
}else if(enemy.HPLower){
status = AI.FindBunker();
}else if(enemy.CloseToPlayer){
status = AI.Attack();
}else if(!enemy.CloseToPlayer && enemy.DistanceToPlayer){
status = AI.MoveToPlayer()
}else{
status = AI.Patrol();
}
}
FSM相比于朴素AI的优点:
- 可以通过分类封装接口,让每一种AI调用接口来实现状态的迁移
- 不需要实时计算各类函数,减少计算产生的损耗
但是也有缺点:
- AI越智能,状态流程图就越复杂,后期难以维护
- AI的功能难以扩展,新加状态的时候需要考虑目前状态间的关系
Ⅲ.AI行为树 (Behavior Tree,BT)
Behavior Tree是一种树状的数据结构。每次调用都会从根节点开始遍历,自顶向下,通过一些条件来检索这颗树,最终确定需要做的行为并执行。下面是一个简单的行为树:
在游戏中,行为树的父节点统称控制节点,而子节点则称行为节点。
- 控制节点:当AI接收到来自游戏中的某一条件时,就会开始遍历这颗行为树,例如:Attack的时候就会从根节点遍历到Attack这个节点上去,并且执行该节点下的行为。这时候的控制节点的作用就是接收信息并对信息进行决策筛选,它没有执行具体操作的功能。
- 行为节点:行为节点处于树的最底端,是最后一个接受信息的地方,意味着它需要对控制节点筛选出来的信息进行具体的操作反馈,是执行具体状态行为的地方。
事实上,行为树又称决策树,因为整棵树最主要的部分是控制节点,它需要对条件进行决策,判断出需要执行的正确的行为。
行为树的优点不仅在于它逻辑清晰,而且我们可以对其控制节点自定义判断。一般简单的自定义控制节点有三种:
- 选择(Selector):根据条件信息,只选择其子节点的某一个执行。
- 序列(Sequence):根据条件信息,将其所有子节点依次执行一遍,只有当前一个子节点返回“完成”状态后,才能继续运行下一个子节点。
- 并行(Parallel):根据条件信息,将其所有子节点都运行一遍。
不过单独使用行为树也是有缺点:
- 行为树后期分支数量庞大,每次遍历寻找合适节点的过程消耗高。
- 如果需要序列或并行状态,需要对整棵树进行多次遍历,过程繁琐。
Ⅳ.个人总结
无论是什么游戏,游戏AI所使用的最好的方法从来不是一个,而是通过不同类型AI来寻找适合该时期使用的方法:状态机+行为树,朴素AI+状态机+行为树等等。随着游戏的不断发展,游戏AI也还有很大的成长空间,会有更多的算法和优化方法去构造更加智能的游戏AI。