游戏中常用的 AI 实现方案

游戏中 AI 的使用场景一直很多,好的 AI 可以画龙点睛。

基础 AI 设计

  1. 远程攻击单位(Ranged):超过最大跟随距离,执行 follow,小于攻击距离,执行 flee,逃离目标,小于跟随距离大于攻击距离执行 idle 或者 attack;
  2. 近战攻击单位(Melee):超过最大跟随距离,执行 follow,小于攻击距离,执行 idle 或者 attack;

这个 AI 设计虽然简单,却可以满足很多游戏 NPC 的需求。

常见 AI 以及实现

  1. 靠近 seek,速度向量差 (TargerPos - CurrentPos) * CurrentSpeed,Tick 计算 AI 坐标,执行移动;
  2. 离开 flee,速度向量差 (CurrentPos - TargerPos) * CurrentSpeed,然后根据当前方向移动(反方向)移动;
  3. 抵达 arrive,类似靠近,速度值根据阀值递减,实现慢慢靠近的效果;
  4. 追逐 pursuit,目标正前方直接走过去,限制角度(比如20以内),预测目标点。设置一个合理的预测时间,建议预测时间正比于逃避和追逐者的距离,反比于两者速度;
  5. 逃避 evade,类似追逐,远离预测位置;
  6. 徘徊 wander 设置一个 wander distance,然后根据这个 distance 随机一个点,AI 执行 move,移动过去。设置一个 wanderRate,控制徘徊频率;
  7. 回避 avoidance(RVO),比较复杂…TODO
  8. 巡逻 patrol,地图设置几个巡逻点即可,遍历各个巡逻点,循环移动;

以上是常见的AI行为的实现思路。

复杂 AI 设计

实现 AI 引擎结构

  1. 制定决策(Decision Making)
  2. 移动(Movement)
  3. 路径规划(Path Planning)
  4. 感知(Perception)

Fuzzy AI,是很多游戏使用的AI设计基础,比如足球游戏、比如格斗游戏等 (模糊逻辑)。
工作室预研过一款格斗游戏的研发,是我主导的,AI的技能系统就采用了以下这种方式。效果很好。

基于 Fuzzy AI 设计格斗游戏 (动作游戏) AI

AI Rule

  1. AI Condition 比如攻击对象、攻击距离、双方的血量变化等来作为AI触发的条件
    Attacking_AttackType_Self,Attacking_AttackType_Opponent,就是使用某个技能进行攻击行为,该行为可以作为 AI 触发的条件,又比如 Distance_Self,Distance_Opponent,敌我距离判断,这个也可以作为 AI 触发的条件。
    HealthStatus、MovementSpeed等也可以作为 AI 触发的条件。

  2. AIRule 各种条件根据关键字组成很多的条件语句,输入到 AI Engine,产生很多行为。

 string Rule_AND = " AND ";
 string Rule_Close_Parenthesis = ") ";
 string Rule_IF = "IF ";
 string Rule_IS = " IS ";
 string Rule_NOT = " NOT ";
 string Rule_Open_Parenthesis = " (";
 string Rule_OR = " OR ";
 string Rule_THEN = " THEN ";
  1. AIReaction AI 产生 Idle、MoveBackward、PlayMove_AttackType_Projectile 释放远程技能、PlayMove_Damage_Weak 等等各种行为

  2. 根据 AI Rule 初始化 inferenceEngine 一定间隔内输入更新 inferenceEngine Input 信息(比如当前血量)等和 Output 信息(不是所有Output都有效的,比如眩晕状态下无法释放技能),
    间隔长短决定 AI 难度。

AI Engine (模糊逻辑)原理

根据条件生成隶度值(模糊),多个条件生成的多个隶度值根据最大平均数计算法求出正常值(去模糊化);
本质上是根据条件算结果。


模糊系统,主要用于解决决策性 AI 系统设计的两大痛点,即 AI 行为的自然程度,以及系统平衡性的维护。
基于 Fuzzy AI 所产生的 AI 可以综合当前位置、血量及敌方行为的整体情况,来决定下一步是逃跑、撤退、攻击或是补充血量,或是根据玩家行为发生的时间与地点将玩家进行归类。
AI还会将多种关联因素产生的行为随机化处理,这样的设计能够让AI更接近于真实玩家,表现得更为自然。

 IF(温度“冷”)然后(加热器“高”)


该规则使用“温度”输入的值,这是“冷”的一些值,以在“加热器”输出的模糊集中生成结果,这是“高”的某个值。 此结果与其他规则的结果一起使用,以最终生成清晰的复合输出。显然,“冷”的值越高,“高”的值就越高,尽管这并不一定意味着输出本身会被设置为“高”,因为这只是众多规则之一。 在某些情况下,逻辑函数可以通过相当于副词的“对冲”来修改。常见的对冲包括“约”,“近”,“接近”,“近似”,“非常”,“略微”,“太”,“极端”和“有点”。 这些操作可能具有精确的定义,但不同实现之间的定义可能有很大差异。 对于一个例子,“非常”是正方形隶属函数;由于成员资格值总是小于1,因此会缩小隶属函数。 “非常”将数值分块以提供更大的缩小,而“稍微”通过取平方根来拓宽功能。

群组 AI 设计

我们通常理解的鱼群算法,使用场景比如 MOBA 游戏的小兵 AI,以及最近很火的一个 IO 类游戏,吞噬星球,玩家带带一堆小兵去吃其他的人,小兵越来越多等等。
Group Behaviour-组行为

  1. alignment - 队列,企图保持和邻居朝向一致;
  2. cohesion - 聚合,产生力使得 AI 移向邻居的质心;
  3. separation - 分离,产生力使得 AI 离开附近的邻居;

举个聚合算法的例子:

FVector AverageHeading;
for (int a = 0; a < Neighbors.Size(); ++a)
{
  AverageHeading += Neighbors[a]->Heading();
}
if (Neighbors.Size() > 0)
{
  AverageHeading = AverageHeading / Neighbors.Size();
}

如果 AI 本身在 Neighbors 中的话,记得过滤掉。
每一帧计算队列、聚合、分离,然后按照加权比例,把三种行为的向量加在一起,就是我们AI当前帧的目标方向;
合适的加权比例需要花时间来调整。

总结

其他的用于 AI 的技术点,比如状态机、行为树等,都是老生常谈的东西,Sequence(And)、Select(Or)、Parallel 节点配合实现各种各样的 AI,同时配置驱动的话就很好了。

For more details see
1-artificial_intelligence_fuzzy_logic_systems
2-Fuzzy_control_system
3-AForge
4-AI
5-AI