人工智能实战:智能NPC知乎分享

大家好,我是来自畅游引擎部的考拉,今天来做一个有关智能NPC技术的分享。

1、背景
在许多游戏中NPC一直是不可缺少的一部分,但是随着近些年大世界题材游戏的火热,氛围型NPC越来越引人关注,策划可以通过这些氛围型NPC来讲述游戏世界观,玩家也可以通过观察NPC的行为来有更多的沉浸感,但又因为该部分不是游戏的核心逻辑性价比不高,如何生产这些氛围型NPC一直是个问题。
一般来说,NPC表现的好坏取决于策划的配置是否完备,只有将玩家能想到的情形都配置出来,玩家的体验才可以保证,但这样的工作量对于策划和程序都是灾难级的。所以经过一段时间的研发我们产出了一个智能NPC系统,策划可以通过简单的配置就能大量生成比较高质量的氛围型NPC,下面是一些关键技术的分享。

2、关键技术
(1)底层驱动:
智能NPC系统里的NPC是按照行程表进行驱动的他们都会日出而作日落而息。


如上图所示,是一个NPC的行程表示意图,到了行程表上的时间节点就会执行下一个动作。在代码层面上不同动作的具体实现是通过模版来实现的,比如摆摊的行为模式是一个模版,巡逻的行为模式是另一个模版,在如果NPC的行程表从从摆摊变为巡逻那么只需要切换其装载的模版即可,可以减少功能的重复开发。这些模版的底层实现是通过腾讯的开源行为树编辑器behaviac实现的。这种图形化的编辑器比较适合策划和程序的合作。

(2)事件触发

除了行程表驱动NPC之外,我们还想让NPC具有对环境的感知能力,比如可以和路过的玩家进行打招呼,比如像上图一样可以被跳舞的人所吸引,自发地围观跳舞。

这个功能需要向周边的人广播跳舞的事件,所以自然需要AOI系统,在智能NPC系统中,我维护了一个带有哨兵节点的十字链表,当有节点在Update时跨越了某个NPC的哨兵节点,则为进入或离开了这个NPC的AOI范围,下文是Update时的代码。

 public void UpdateAOI(int id, Vector3 newPos)
    {
        OrthogonalNode main = nodeMap[id];
        Vector3 offset = newPos - main.pos;
        main.pos = newPos;
        main.xSentryHead.pos += offset;
        main.xSentryTail.pos += offset;
        main.ySentryHead.pos += offset;
        main.ySentryTail.pos += offset;
 //根据Offset的大小改变移动节点的顺序
 if (offset.x < 0)
        {
            MoveToCorrect(main.xSentryHead, _handleWhenMoveSentryNode, MoveType.E_MT_OnlyX);
            MoveToCorrect(main, _handleWhenMoveNode, MoveType.E_MT_OnlyX);
            MoveToCorrect(main.xSentryTail, _handleWhenMoveSentryNode, MoveType.E_MT_OnlyX);
        }
 else if (offset.x > 0)
        {
            MoveToCorrect(main.xSentryTail, _handleWhenMoveSentryNode, MoveType.E_MT_OnlyX);
            MoveToCorrect(main, _handleWhenMoveNode, MoveType.E_MT_OnlyX);
            MoveToCorrect(main.xSentryHead, _handleWhenMoveSentryNode, MoveType.E_MT_OnlyX);
        }
 if (offset.z < 0)
        {
            MoveToCorrect(main.ySentryHead, _handleWhenMoveSentryNode, MoveType.E_MT_OnlyY);
            MoveToCorrect(main, _handleWhenMoveNode, MoveType.E_MT_OnlyY);
            MoveToCorrect(main.ySentryTail, _handleWhenMoveSentryNode, MoveType.E_MT_OnlyY);
        }
 else if (offset.z > 0)
        {
            MoveToCorrect(main.ySentryTail, _handleWhenMoveSentryNode, MoveType.E_MT_OnlyY);
            MoveToCorrect(main, _handleWhenMoveNode, MoveType.E_MT_OnlyY);
            MoveToCorrect(main.ySentryHead, _handleWhenMoveSentryNode, MoveType.E_MT_OnlyY);
        }
}

通过十字链表可以以一个比较小的开销实现AOI功能。解决了AOI问题后还会有以下问题:在什么地方进行围观事件的广播,在跳舞的模版里进行广播的话会不会造成功能上的不合理耦合;怎么确保来围观的人能够大致站成一个圆圈;行程表中的大部分行程为了模板化都可以拆解为什么时间去什么地方干什么,围观跳舞这个动作的地点怎么确定。

为了解决以上问题,我们设计了一个基于地点的事件触发系统,事先设定好跳舞的舞台和其周围均匀分布的围观跳舞的地点,当有NPC来舞台上跳舞时,舞台上绑定的事件被触发,向周围的NPC广播来围观的信号,目标是设定好的围观地点,如果收到广播信号的NPC愿意前来,就会走到围观点播放鼓掌动画。通过这样的设计,在代码层面将跳舞、广播事件、围观三个动作进行了解耦,方便后续的代码维护和策划的灵活配置。

(3)强化学习生成行程表

设计实现好模版、事件触发等基础机制后,我们来介绍智能NPC被称为智能的核心点,那就是由借助强化学习的AI技术,让NPC不通过策划配置,而是自行决定自己的行程表。

强化学习适合解决连续决策问题,看似和生成行程表毫不相关,但是我们在设计上对其进行了一些转化,为每个NPC设置初始属性和目标属性,再为每个可执行的行程设定好其对NPC的影响,最后设计一个模拟的游戏环境让强化学习模型去学习这些行程,最后强化学习模型就可以根据NPC当前的属性和目标的属性为其设计出最适合的行程表,通过这种设计将行程表的问题转化为了连续决策问题。

从表现上来说,如果一个NPC开始很贫穷,但是目标是成为一个很富有的人,那么在强化学习的影响下他每天的行程就会更倾向于摆摊而不是散步游玩。

3、总结

总体上来说,智能NPC系统将策划配置NPC的工作模式从精细地设定每一个NPC的行为,转变为了设定NPC世界的规则,在这种规则下,只需要简单的配置目标属性和当前属性就能快速产出大批量生动的氛围型NPC。

欢迎加入我们!

感兴趣的同学可以投递简历至:CYouEngine@cyou-inc.com

  • 9
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

搜狐畅游引擎部

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值