如何将有限状态机连接到基于组件的体系结构?[关闭]


23

状态机似乎在基于组件的体系结构中造成有害的依赖关系。

具体来说,如何在状态机和执行与状态相关的行为的组件之间处理通信?

我在哪里:

  • 我是基于组件的体系结构的新手。
  • 我正在制作格斗游戏,尽管我认为这并不重要。我设想我的状态机将用于切换“蹲下”,“破折号”,“阻塞”等状态。
  • 我发现这种状态管理技术对于基于组件的体系结构来说是最自然的系统,但是它与我读过的技术相冲突: 用于可变行为角色的动态游戏对象组件系统它建议所有组件都激活/停用通过不断检查激活条件来检查自己。
  • 我认为像“跑步”或“步行”之类的动作在状态上是有意义的,这与此处接受的响应不同:https : //gamedev.stackexchange.com/a/7934
  • 我发现这很有用,但是模棱两可:如何在基于组件的游戏架构中实现行为?它建议有一个单独的组件,其中仅包含状态机。但是,这需要在状态机组件和几乎所有其他组件之间进行某种耦合。我不明白该如何处理耦合。这些是一些猜测:

    A. 组件取决于状态机:
    组件接收对状态机组件的引用getState(),该引用返回枚举常量。组件会定期进行自我更新,并根据需要进行检查。

    B. 状态机取决于组件:
    状态机组件接收对其监视的所有组件的引用。它查询他们的getState()方法以查看它们的位置。

    C. 它们之间的某种抽象
    使用事件中心吗?命令模式?

    D. 使用引用组件
    状态模式的单独状态对象。创建了单独的状态对象,这些状态对象激活/停用一组组件。状态机在状态对象之间切换。

  • 我正在将组件视为方面的实现。他们在内部完成使该方面实现所需的一切。看起来组件应该独立运行,而不依赖其他组件。我知道一些依赖是必要的,但是状态机似乎要控制我的所有组件。

Answers:


7

概述非常简单,但是请查看我去年为New Game Conf做的一个演示文稿中的以下幻灯片:

https://docs.google.com/presentation/d/110MxOqut_y7KOW1pNwIdcccisIA3ooJwVR-xm-ecuc4/view

(请参阅下面的相关图片)

该技术的要旨是将动作列表模式(在幻灯片中解释得有些差(在幻灯片中有所说明))与作用于基于组件的游戏实体的行为状态机相结合。

从本质上讲,这与为AI行为创建特殊的合成系统相同,旨在满足您需要更简单的AI系统的各种行为间集成。

在该特定游戏中,我最喜欢的部分是我们如何通过简单地从预先编写的行为列表中进行选择,从而按照所需顺序将它们放入游戏对象(位于BrainComponent中)的动作列表中,从而创建全新类型的敌人。优先,一切都正常。通过允许阻止/非阻止动作的动作列表,尽管实现起来很简单,但它可以做一些非常酷的事情。

甚至像“眩晕”之类的行为,实际上只是一个StunBehaviorAction进入了动作列表堆栈的顶部;如果激活了眩晕行为(观察到游戏对象的EarsComponent听到了惊人的冲击波攻击),则将其内部状态设置为Stunned,告知AnimationComponent播放眩晕动画,并将其动作状态设置为Blocking,并将其计时器设置为从游戏对象的EnemyParametersComponent中拉出的眩晕超时。由于它是“阻止”并且在操作列表的顶部,因此操作列表中的其他BehaviorAction都不会调用其update方法,因此实际上将其关闭。超时到期后,StunBehaviorAction会将其状态设置回Idle,将其动作状态设置为NonBlocking。

我们实现的其他行为几乎都是用单个内部状态机实现的。实际上,仅有的两个没有状态机的是PatrolPathBehaviorAction(如果空闲,它将把一系列PathAction推送到动作列表上,然后将其推送到MoveAction上)和GuardHomeBehaviorAction(始终位于状态列表的底部)。动作列表,并且总是将PathAction推回到敌人的家中)。其他所有行为都是状态机。

投影片10 投影片25 幻灯片26


“行为”和“动作”之间的根本区别是什么?
2012年

1
@Pup:从代码角度来看,在我构建代码时,“行为就是行为”。从概念上讲,动作通常是暂时的-它们只存在到“完成”为止-而行为是永远的,永远不会从列表中删除。我已经看到另一个团队构建了一个类似的系统,但是有两个列表,一个列表用于操作,一个列表用于行为,它们运行良好。但是,我喜欢使用位屏蔽和分组(“车道”,我相信我在幻灯片中称它们为“动作”)可以阻止某些行为。抱歉,中间幻灯片的图形太糟糕了。:)
肖恩·米德迪奇

3

在之前的公司工作过,我们有一个基于组件的系统和基于状态的AI。我们有一个AI组件来控制该对象/单元的所有行为。当AI处于活动状态时,例如徘徊,攻击等,它将在每帧接收更新,以执行所需的任何逻辑。当AI空转或不移动时,组件将停用,并且不会在每个帧中更新。该组件在停用​​后仍可以接收基于事件的消息,因此它将收到一条消息,例如玩家输入其敏捷半径之类的消息,并可以通过重新激活AI组件对此做出响应,从而可以执行基于帧的更新。

AI组件具有子组件,可以根据正在执行的操作类型即时创建和销毁这些子组件。例如,如果它在游荡,则可以创建一个在游荡的子组件,并在游荡时更新每个帧,然后,如果在游荡的过程中发生仇恨,则会关闭该子组件并打开攻击子组件。AI组件应独立于对象上的所有其他组件。例如,我们有一个输入组件,可以简单地查询一个单元上的运动值。它提出的查询是人类和AI对象都可以响应的查询。这使AI组件可以在诸如徘徊之类的过程中简单地设置输入组件可以拾取的移动值,就像人类可控制的组件可以设置输入组件可以拾取的值一样。


那么,AI子组件实际上是在做这项工作吗?它们是否以与AI组件相同的级别作为实体组件存在?
2012年

我们引擎中的子组件是基本组件类的一部分。因此Component,从派生的BaseComponentany可以包含任意数量的SubComponent。中的Update()方法BaseComponent将检查子组件列表,然后调用Update()这些子组件。Subcomponents是完全可选的,因此BaseComponent可能没有任何内容。同样,所有发送到组件的消息也将路由到子组件。
Nic Foster

1

组件的含义还不清楚,因为您的用语非常模糊,没有具体示例。通常,游戏实体是使用合成而非继承来构建的。因此,您可以通过向实体中添加健康组件来使它们成为可能受到损害的东西,或者可以通过添加动画组件来使它们成为动画。也可以将AI放在这样的组件中。AI组件中将存在决策逻辑,如果您担心将其与系统中的许多其他代码耦合,则可以将信息收集到黑板中,仅允许AI逻辑访问。还存在依赖于AI系统输出的问题。基本上,您的AI正在控制一个实体,而该控件需要一个接口。一个有用的概念是控制器或游戏手柄的概念。您的AI可以填写与玩家游戏手柄相似的结构(尽管它可能具有一些用于特定功能的“额外按钮”)。现在,可以将此结构传递到动画组件,该组件将对其进行解释并选择要播放的动画。不同的AI子组件甚至可以写入结构的不同字段或具有不同优先级的相同字段。例如瞄准和行走。不同的AI子组件甚至可以写入结构的不同字段或具有不同优先级的相同字段。例如瞄准和行走。不同的AI子组件甚至可以写入结构的不同字段或具有不同优先级的相同字段。例如瞄准和行走。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.