【Unity小技巧】AI 是如何实现的?

前言

刚刚在逛论坛的时候发现一个讨论有关 NPC 的 AI 是如何实现的帖子,于是思考了一下,想到其实利用订阅发布者模式就可以很方便的实现 AI 系统了。

订阅发布者模式:https://huotuyouxi.com/2021/09/24/unity-tips-006/

游戏场景

AI 就是让 NPC 具有“独立思考”的能力,虽然说是独立思考,但其实也不过是写好的一套程序,但是可以通过某些「数值化」来让 NPC 有不同的行动,NPC 会根据一些数值的变化来制订自身的行动方案,更进一步来说,如果要完全实现由 AI 控制的 NPC,可以用程序制定好一套“性格系统”,比如“暴躁”的性格,NPC 对于“容忍度”(某个数值条件)就会越低,比如玩家偷了他家里的东西,他是无法容忍的,就会直接攻击玩家;而性格“温和”的人,“容忍度”就很高,如果玩家到家里偷东西,他会视而不见。“性格”是各项数值的评判标准,对于泛型的 NPC 来说,只需要指定这个 NPC 的性格,他就会按照自己的“意识”进行行动了。

例如玩家如果杀了一只鸡,全村的人就会来追杀你。

这个应该如何实现呢?直接使用 if-else,那整个村子里的 NPC 都得来一个 if-else 结构,很明显累死都写不完。那么我们完全可以这样做,首先是给所有的 NPC 加上一个「友好度」的概念,友好度是一个数值,假设最低是 0,最高是 100,玩家杀了一只鸡,全村 NPC 的友好度会直接变成 0,当友好度为 0 时,NPC 对玩家就是敌对状态,如果 NPC 处于敌对状态,在遇到玩家的时候就会追杀。

这样就很简单了,只需要指定一套『友好度』的标准,NPC 就会根据数值来进行不同的行动,实现这套系统的最好方法就是订阅发布模式。

消息的广播

玩家杀了一只鸡——这是一条消息,只要把玩家杀鸡的消息广播给所有村民,村民在得知这个消息之后就可以做出不同的反应。普通的村民在听到你杀了鸡,就会变得怒不可遏,对你的友好度直接下降到 0,然后开始追杀你。而你的队友,在看到你杀了鸡,并且获得了“鸡肉”,不仅不会生气,反而会增加友好度变得更亲密了。

玩家在游戏世界里做的每一件事都是一条「消息」,比如玩家完成了公会的委托,那么消息机制就要把玩家完成委托的消息广播给全世界,至于 NPC 对这条消息是否在意,就需要根据 NPC 的性格来制定了,不同的 NPC 会对这件事做出不同的反应,例如你的小迷妹在听到你击杀了恶龙,对你的友好度就会上升。

数值系统

AI 的行动可以依靠数值进行判定,数值有很多种,所有的数值经过某种『规则』计算之后,NPC 就会执行某种命令。

由于数值众多,就需要有一个计算「权重」的公式,假设一个 NPC 有下面这几种数值:

  • 心情(feel)
  • 武力值(attack)
  • 饥饿度(hunger)

NPC 每天都会决定自己今天要干什么,比如他会做三件事:①打猎,②睡觉,③杀死其他 NPC。

那我们可以简单的实现 NPC 的 AI:

1
2
3
4
5
6
7
8
if(feel < 10 && attack > 50 && hunger >= 100 ) {
killOtherNPC();
} else if (feel < 10 && attack <= 50 && hunger >= 100) {
sleep();
} else {
// ... 其他行动模式
}

如果心情低于 10,且武力值大于 50,且饥饿度大于等于 100,该NPC就会去杀其他 NPC,通过这种方法在饥饿状态下击杀其他 NPC 抢夺食物饱腹;如果武力值低于 50,NPC 即使在饥饿状态下,也会认为自己太弱小而不敢去攻击别人,因此选择睡觉。

上述场景就实现了一种简单的 AI 行动模式,但是这样 if-else 来判断,不可能模拟所有的场景,工作量实在太大了。因此我们可以通过计算「权重」的方式来决定 NPC 一天的行动。

同样是上面的场景,我们可以假定 NPC 是否会去攻击其他玩家,三个数值的重要顺序依次是:①武力值,②饥饿度,③心情。如此一来我们便可以根据重要顺序来给 NPC 进行“打分”,比如武力值的系数是:1.0,饥饿度的系数是:0.8,心情的系数是:0.5,然后将三个数值与系数相乘,最终得到一个『分数』,NPC 会根据这个分数的值来决定行动模式:

1
2
3
4
5
6
7
8
9
10
float score = attack * 1.0 + hunger * 0.8 + feel * 0.5;

if(score > 50) {
killOtherNPC();
} else if (score > 20) {
hunter();
} else {
sleep();
}

当分数大于 50 的时候,他就会去攻击其他 NPC 抢夺食物;当分数大于 20 且小于 50 的时候,他就会选择去狩猎获得食物;其他情况就会选择呆在家里睡觉。(因为自己的武力值很低,而且又十分饥饿,打不过其他 NPC,也打不死动物,就只能待在家里等死了。)

上面就是一个根据「权重」来计算 NPC 行动 AI 的方式,对应的系数取决于我们给 NPC 设定的“性格”,根据性格因素的不同,对应的系数也不一样,比如好斗的 NPC 他的物理系数就比其他 NPC 要高,当他的武力值达到某个水平就会“仗势欺人”。

总结

要实现 AI 系统,让 NPC 有独立思考能力,可以通过下面的方法来实现。

消息广播机制

通过订阅发布者模式,来让 NPC 产生动态变化的数值,比如玩家做了一件事,某个 NPC 的好感度就会变化;而某个 NPC 做了一件事,其他 NPC 也会产生某些变化,这样动态改变的因素很多,NPC 的行为也会影响到其他 NPC,游戏的随机性就会变得很强。

如果要让强盗知道什么时候才应该去拦路抢劫,就在玩家获得某件宝物的时候“通知”强盗就好了!

这是「事件驱动」模式,玩家或者 NPC 所做的每一件事都会进行广播,玩家击杀了恶龙,国王听到消息就会发来赏赐,强盗听到国王发给你赏赐的消息,就会拦路抢劫,某个热心路过的 NPC 看到你被强盗抢劫,就会过来帮你一起战斗……诸如此类,一件事只要被广播出去,然后其他的 NPC 就会做出不同的决策,而做出什么决策取决于 NPC 的数值。

性格机制

除了某些剧情的 NPC 是固定行为模式,比如魔王会在某时某刻出现在玩家面前,这种固定的模式都是程序写死的,是必然发生的事件,因此不涉及 AI 概念。对于村民之类的普通 NPC,我们要让他们会根据自己的“思考”行动产生很多变数,我们就可以设定好一套「性格系统」,NPC 在出生时赋予一个性格,不同性格下,某个属性的成长速度就会不一样,因而产生出更多的数值变化。

数值的变化就是游戏随机性的根本条件。

数值行为机制

NPC 的行动依据是根据自身的数值综合计算之后的结果,也就是有一套『权重计算』机制,根据最终得到的“分数”来决定 NPC 的行为模式,这个计算方式就是 AI 最核心的部分了,沙盒游戏好不好玩,主要就是取决于如何计算的,当然我也不是专业的,无法再详细的解释下去。

做一个沙盒游戏?

NPC 具有独立思考的游戏现在十分常见,而且百玩不厌。
要不要制作一个沙盒游戏呢?有些心动!

一个战争模拟类型的游戏,NPC 会占山为王,而那些村民们则会根据自己的性格选择加入或者逃亡去投靠别的国家,那些成为王的 NPC 们,则会与其他国家结盟或者发起战争,一旦战争发动,就会有村民逃离,他们会去哪呢?如果你是一个新的王,会选择接收这些难民吗?而你又该如何发展壮大自己的国家,去招募那些拥有「独立思考」能力的武将呢?当你弱小的时候,没有一个武将看得上你,但是也有可能发生奇遇,像从公孙瓒手中得到猛将“赵云”呢?也许一次随机事件,让你救下一位重伤的猛将,因此成为你的左臂右膀!充满变数的这个世界,每个 NPC 都是“活”的,他们也会痛苦,他们也会悲伤,他们不再是那个站在路边只会为你鼓掌的路人甲,他们每一个都可能成为这个游戏的主角,而作为玩家的你,已经不再享有主角光环,立场与那些 NPC 一模一样的时候,你又该如何掌控自己的人生?

现在一个游戏都没做出来,要怎么才能开这个新坑呢o(╯□╰)o

文章作者: 火烧兔子
文章链接: http://huotuyouxi.com/2021/10/02/unity-tips-008/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 火兔游戏工作室