【游戏精粹】独立非玩家角色合作行为的实现

前言


        本文讨论了一些可以容易添加的机制,这些机制可以使独立的非玩家角色具有更多的合作性。尽管每一个非玩家角色独立地决定它自己的行为,增加一些附加的信息并简单地进行通信将使得游戏看起来好像真的发生了合作行为一样。


    可能的解决方案


        合作,能够用很多方法来解决。一种解决方案是什么也不做。一些游戏类型避免了添加复杂的合作行为,因为敌人被假定为只会混乱地行动(例如《植物大战僵尸》中的僵尸彼此之间没有合作,而巨人僵尸的投掷行为与梯子僵尸的行为只能算是简单的合作行为)。然而,通常的情况并不是如此,有两种传统的方法来解决合作问题:通过集中控制的游戏实体,或者通过给每一个游戏实体更多独立的控制。
        1.集中控制的方法
            传统地,人们在游戏中使用集中控制的解决方案。在这样的解决方案中,一个并不一定要代表某个真实的游戏实体的智能代理分析玩家和所有非玩家角色的情况。当得到所有的信息后,它进行计算得到一种合作策略。为了执行这一策略,它给每一个人工智能代理发出指令。如果一切顺利,所有的非玩家角色将以一种完美的合作方式进行行动,尽管它们只是在盲目地执行指令。
            一些游戏设计者需要严格地控制非玩家角色的行为。在这样的情况下,固定的且缺少独立性的组织方法将会是最好的选择,因为这样设计者可以更好地实现控制的层次。
            尽管一些游戏获益于智能代理的自治性,然而,对于合作行为采取集中式的解决方案能够提供一个更容易控制的系统。如果设计者需要一个在特定情况下发生的具体合作行为,只需在集中式的智能代理中直接添加一些优化代码即可,这比修改一批独立的机制以使它们在特定的情况下有特定的行为要容易。而且,集中式的方法也容易修改排错,容易将行为和不同的非玩家角色对应起来。
            集中式的方法最大的缺点在于扩展性:当系统逐步变大时,这样的解决方案也会变得越来越复杂。不仅如此,因为集中控制方法是统一的结构,因此在其计算策略时或者在其执行结束之前,它很难根据变化做出改变。
            总之,集中式的控制方法没有很好的扩展性而且不能很好地适应变化的环境,并且可能耗费很多的CPU资源而影响非玩家角色的响应能力。此外,它很难处理在设计阶段没有预见到的情况。随着多核处理器的出现,给集中式结构的实施带来了更多的障碍,因为将一个进程分开使其能够充分利用多处理器的优势并不是一件容易的工作。
        2.独立控制的方法
            另一种解决方案源于对得到公认的分布式计算策略的探入探究。在分布式的系统中,前面提到的集中式的很多问题都得到了解决。因此,值得推荐的解决方案是将合作任务分配到所有的智能代理中。这样的组织方法提供了一个可扩展的、灵活的结构,通过它,每一个智能代理都可以被分配一个独立的线程来执行。非玩家角色们通过自行决定要做什么而变得独立起来。它们不再仅执行指令,而是主动参与了决策的过程。
            合作,通过在独立的智能代理通信和共享信息而自然地显现出来,而不是显式地通过编码实现。当解决简单的局部问题的时候,很容易找到一个解决方案为每一个智能代理选择一个最好的行为,接着,才把合作当作一个单独的问题考虑。任何时候都没有全局的策略。这种方法允许当大的游戏情况发生变化时出现相对应的一些行为的调整,而不必重新计算一个全新的全局策略。
            因为非玩家角色是完全独立的,当我们需要的非玩家角色增加时,这种解决方案可以自如地扩展系统规模。当添加新的非玩家角色,并且要让它们使用相同的合作机制时,独立控制方法显然比创建一个集中控制实体来考虑处理这些新非玩家能要容易得多。分布式的解决方案也解决了多核硬件处理的问题,因为每一个非玩家角色都可以被指定到一个不同的线程上执行。多线程的编程问题仍需面对,但这样的计算框架下,任务的分解已经不是问题了。
            任何人工智能控制的实体的响应速度都是不需要担心的,因为每一个人工智能代理独立地决定该做什么,它的决策过程的计算时间要比集中式解决方案中全局策略的计算时间要短。
            该方法缺点:让一组独立的实体合作起来以使他们做应该做的事是一个挑战。而且,在没有专用机制的情况下,对群组行为进行细微的控制会非常困难。


   非玩家角色的结构


        我们致力于完全独立的非玩家角色,所以系统必须提供他们这么做的所有能力。有了这个目标,我们就可以选择一个灵活的结构来表达游戏智能代理。它包含一些控制单元,这些控制单元用来完成智能代理在游戏中必须执行的任务。
        一个典型的非玩家角色应该能够做动作,在关卡中移动,感觉周围的世界,并在感觉的基础上采取行动。为了完成这些任务,系统定义了动作、移动、感觉、行为控制器。

非玩家角色的结构与连接

        本文将特别介绍行为控制器部分。行为控制器用来控制行动的执行,也就是控制在游戏中的每一个时间片代理做什么。有些很简单买入跳开以免击中,有些复杂,如boss的攻击例程。它们可以组成树状结构或层次结构来将简单的行动构建成更复杂的行动。控制器包含一组正在活动的行动,这些行动在每一帧画面更新时执行,并且有一组等待的行动,这组行动持续地监听执行条件是否符合,在符合的时候就开始执行行动。
        这样的组织方法给系统带来了很大的灵活性。当新的行动在搜集所需的数据时,旧的行动将依然保持活动的状态,直到完成数据收集,执行新的行动。这些特效使合作系统的要求不再那么高。我们可以花更多时间去调节各种行动使其更好地合作而不用担心角色被冻结。


    合作机制


        因为非玩家角色是自己做出决定,最好的办法是提供一个机制让它们来交换信息。通过这种方法,他们中的每一个都可以得到所有需要的信息以便做出一个深谋远虑的决定,确定执行什么样的行动,在哪里执行。
        本文提出了在非玩家角色之间交换信息的若干机制:

      • 攻击口;
      • 独占区域;
      • 触发系统;
      • 敌人事件;
      • 玩家互斥器;
      • 允许区域;
      • 黑板;

        这些机制不是企图建立超级智能的代理。它们只是提供简单的解决方案,当这些方案组合起来工作的时候,就能够模拟出多个智能代理协同工作的效果。
        1.攻击口
            在同一时间里多个敌人对玩家发起攻击,如果他们都单独地做出决策,他们可能都觉得近距离攻击玩家最好。这样的情况下,所有敌人将包围玩家,并可能相互阻挡。显然,这不是一个期望的结果,这种现象的发生是因为非玩家角色在作决定时缺乏其他非玩家角色的必要信息。
            作为一个普遍的原则,最好将敌人分散在有效空间中而不是挤在玩家周围。最好的办法是建立这样的一个非玩家角色,他能够进行情况分析,考虑地形拓扑结构、其他非玩家角色的位置、游戏需要的难度,最后他做出决定从哪儿攻击。然而,因为其复杂性和可用于此类计算的CPU时间有限,拥有这样的智能代理并非总是可行的。
            攻击口以一种方便的方法解决了这个问题。攻击口就像一个令牌,标记了一个最小攻击距离,非玩家角色有什么样的令牌,就表示他对玩家的攻击不能小于什么样的最小距离。

            这些攻击口可以调整分散非玩家角色,它们可以被指定到每一个关卡和每一组敌人中。每一个进行攻击的非玩家角色必须占有一个攻击口,并且他里离玩家的距离不能比攻击口规定的距离近。
            每当非玩家角色寻找一个位置进行攻击的时候,他就请求一个最好的攻击口(距离最近)。当得到这个攻击口后,他就开始进行计算以找到符合攻击口要求的攻击点。当攻击结束后,非玩家角色就尝试换一个最不严格的攻击口——即找一个离玩家至少要比当前的攻击口要远的攻击口。若新选择的攻击位置比原先的最好攻击口所允许的远,则非玩家角色就放弃当前攻击口而选择那个较不严格地——所有的非玩家角色都允许另一个非玩家角色使用原先的攻击口以使后者可以在需要的情况下更接近玩家。
        2.独占区域
            尽管攻击口解决了非玩家角色拥挤的问题,但它只不过设置了一个最小距离要求罢了。这一点可以用相互重叠的攻击口充分说明。在仅有一个最小距离要求的情况下,两个非玩家角色可能选择从同一个位置来攻击,如果这个位置对两个攻击口来说都符合距离要求的话,在这样的情况下,非玩家角色没有办法直到该位置已经被另一个非玩家角色占据了。另一个多敌人攻击的问题是阻挡射击线路,这极大地降低了游戏的智能感并且也产生了其他问题,如敌人被友军火力击中。
            独占区域正是解决这些问题的一种方法。它将对场景中的区域和点的可用性增加另一个限定条件。独占区域表明这些区域已经或即将被某些非玩家角色所占有。因此独占区中的点就可以没有限制地做为个攻击点。
            每一个非玩家角色都登记他们正在使用的或者将要用于攻击的区域,包括相应的火力线路。这个区域可能是围绕攻击位置的一个圆或者是非玩家角色独自保护的一个区域。


            

            这些区域在一个公共的地方进行登记以使其他的非玩家角色能够获取这些信息。当寻找一个新的攻击点时(如一个好的掩护地点),那些在独占区域内的位置再搜索时会被排除在外。
            这样的一个机制确保了两个非玩家角色不会选择同一个地点进行攻击。不仅如此,独占区域的拓扑结构、大小、形状都可以根据敌人的类型、行为或者关卡要求进行自定义。
        3.触发器系统
            触发器系统在游戏人工智能中被广泛地运用。它们有多种用途,其中的一个是通信。
            有时通信是基于位置的。在这种通讯类型中,触发器系统在游戏实体间的通讯中非常有用。在非玩家角色发出话语声明或者发出声音时,触发器就变得特别方便。如,一个非玩家角色发现了玩家并发出叫声让对方停止,这个叫声应该为邻近的非玩家角色听到,因而他们可以赶来帮忙。发出警告的行为可以用在发出叫声的位置放置一个触发器来简单实现。在非玩家角色之间的这种类型的通信可以使玩家感觉到非玩家角色的智能,因为一些游戏事件(这里是声音)在游戏中产生了一个真实的反应(这里是另一个非玩家角色赶过来察看或者帮助)。发出声音后产生的反应将比一个事先编码的事件来得真实,因为事先编码的事件不能完全地和玩家的移动相配合。
            

            触发器大多数是用在声音效果中(如爆炸、射击、开门、对话)。但是触发器并不仅仅限制在显式地通讯中。比如一个死亡的非玩家角色,他可能想和任何在附近能看到他的尸体的人“通信”。收到这个通讯的敌人可以发出警告并开始查找入侵者。这种类型的通讯方式,使用触发器比人工地检查附近的非玩家角色是否还活着要容易得多。
        4.敌人事件
            前述的机制提供了在非玩家角色间的一些不太直接的通讯方式。他们通过获得攻击口、登记独占空间或者设置触发器广播事件来达到表明自己意图的目的。通过这些机制提供的信息,其他的非玩家角色就可以相应地调整自己的行为。
            然而,在一些情况下,更直接的通讯是需要的。如一个非玩家角色挡住了另一个非玩家角色,被挡住的角色应该能够直接给阻挡的角色发送消息,通知他让开。
            一个典型的消息传递框架可以用在这种情况下。消息可以被送到一个特定的非玩家角色、一组非玩家角色或者所有角色。消息的处理和游戏的每一帧同步(可以根据实际情况改变)。在收到消息后,如果消息被接受,非玩家角色可以改变他的行为。
            敌人事件可以和触发器组合应用。在一些游戏类型中,动态组队非常有用。在某些情况下,一个非玩家角色决定编组进攻。他产生一个触发器来向附近的单元声明已发布了一个组队要求。收到触发器的非玩家角色用一个敌人事件作为回应(给触发器源,队长),表示他们准备加入这个组。队长就可以分析这些回应,以决定哪些非玩家角色将加入这个组或者完全撤销组队召唤(比如因为一个新的游戏情况发生了,或仅仅没有合格的队员),并切换另一个战术。
        5.玩家互斥器
            攻击口可以通过限制离玩家最近的敌人数目来达到将非玩家角色分散在一定的距离范围内的目的。有时这还不够,我们还需要控制同时对玩家发起攻击的非玩家角色的数目。这在格斗战斗类游戏中特别明显,此时只有一个敌人允许和玩家进行战斗,其他的敌人智能等待或者使用远距离攻击。事实上,对于一些行为,把它看成是对玩家的独占使用是有助于处理的。把玩家看成一个在多个非玩家角色间共享的资源,就可以使用在多线程环境下的传统的资源存取机制,特别是互斥器。
            互斥器是一个标记谁可以获得共享资源的令牌。这这样的情况下,共享的资源是玩家。当一个非玩家角色想进行格斗攻击时,他就视图获得互斥器。如果可以得到(如其他非玩家角色没有拿到互斥器),那么非玩家角色就取得互斥器,其他的非玩家角色如果想进行格斗,就不得不等待,直到当前的互斥器拥有者完成他的攻击。
        6.允许区域
            在一些特定的关卡或任务中,将多个非玩家角色分布在不同的区域是重要的。

            为了使这一切成为可能,我们应该定义敌人允许移动到的区域、允许攻击的区域或者通常执行任何行为的区域。非玩家角色可以穿过不允许的区域进入允许区域的一个位置,但是任何目标地点都不能在允许区域之外。
            使用允许区域,游戏设计者可以设计特定的情况。这样的机制允许设计者将一些设计态的知识直接加到非玩家角色的合作行为中。允许区域也能由非玩家角色设立——如,一个队长指定每个成员的区域,这样来分配可获得的空间并以可能的最佳方式保护关卡(也许可以通过影响力地图来分析最佳位置,每个位置限制成员个数)。
        7.黑板
            黑板系统(模式)是一个在非玩家角色之间交换和发布信息的重要的根据,也可以用来达到合作。它是一个集中式的信息共享机制——一个公共的地方,每一个非玩家角色都可以在这里发布信息以使其他使用黑板的非玩家角色能够根据新的信息来改变自己的行为。这样就实现了一种信息发布者和阅读者之间的隐含合作。可以用黑板发布各种不同的信息——从非玩家角色的企图、理解到行动建议。
            因为黑板要保存各种不同的信息,所有为此目的而特设的黑板不会非常灵活,因为每添加一个新的系统信息类型就需要修改该黑板的定义。黑板系统在游戏中被作为一种强有力的简单的通讯机制广泛使用。因此,值得花一些时间建立一个灵活的系统并使之能够用到别的地方,或者扩展智能代理而无须对黑板的内部工作做任何改动。
            一个通用的资产系统提供了一个好的解决方案。资产可以是任何类型的并能通过名字或者身份号码快速存取的信息。采用这样类型的系统,就能够非常简单地添加新的信息到黑板并且将其状态容易地连续存到硬盘。这样的持续性可用来实现在不同的游戏关卡之间利用已存盘的游戏维持信息或保持数据的延续性。
            对传统黑板数据的优化可以使黑板功能变得更加强大,比如设定一个过期时间就能够自动处理过期的信息,并且避免黑板容量过度增长占用大量内存。


    结论

        本文介绍了几种使用独立的智能代理来很好地表达非玩家角色方法。没有集中控制的命令发给每一个非玩家角色。他们基于自己掌握的信息选择合适的行动。这些信息不一定全部从环境中获得,也可能从其他的非玩家角色那里获得,并且后者使得非玩家角色之间可以相互合作。如果一个非玩家角色知道关于其他非玩家角色正在做什么的细节信息,他就能对自己的行为做出一个正确的选择而不影响其他智能代理的兴趣。
        随着下一代多线程游戏要求的增长,游戏独立智能代理变得更重要了。由于多个线程会被分配到不同的处理器,你可以将CPV密集型的计算放在不同的线程上,并且让行为控制器去处理那些不能确定的等待时间。
        因为独立智能代理是彼此相互独立的,所以可以将它们分配到所有可供使用的处理器。独立代理的工作不会发生什么变化,只是通讯机制必须根据多处理器间信息交换的要求作相应的改变。


学习资源

    • 《游戏编程精粹6》第三章第二节
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值