如何在基于组件的游戏架构中实现行为?


21

我开始在游戏中实现玩家和敌人的AI,但是对于如何在基于组件的游戏架构中最好地实现这一点感到困惑。

假设我有以下玩家角色,可以固定,奔跑和挥舞剑。玩家可以从静止状态和奔跑状态都转变为挥剑状态,但是随后必须完成挥杆,然后才能继续站立或奔跑。在挥杆过程中,玩家无法走动。

如我所见,我有两种实现方法:

  • 创建一个包含所有播放器逻辑的AI组件(与实际组件分离或嵌入为Pla​​yerAIComponent)。我可以轻松地执行状态限制,而无需在组成播放器实体的各个组件之间创建耦合。但是,AI组件无法分解。例如,如果我有一个只能站立,四处走动或只能四处走动并偶尔挥舞剑的敌人,那么我必须创建新的AI组件。
  • 将行为分解为各个组件,每个组件标识一个特定状态。然后,我得到一个StandComponent,WalkComponent和SwingComponent。为了执行过渡规则,我必须耦合每个组件。SwingComponent必须在挥杆期间禁用StandComponent和WalkComponent。当我有一个只会站着的敌人,偶尔会挥舞剑时,我必须确保SwingComponent仅在存在Walkwalk时将其禁用。尽管这允许更好的混合和匹配组件,但是当每次添加依赖项时,它都可能导致可维护性的噩梦,但必须更新现有组件以更好地满足依赖项对角色的新要求。

理想的情况是,设计人员可以通过将组件拖到容器中来构建新的敌人/玩家,而无需触摸任何一行引擎或脚本代码。尽管我不确定是否可以避免脚本编码,但我想使其尽可能简单。

总结一下:我应该将所有AI逻辑分解为一个组件,还是将每个逻辑状态分解为单独的组件,以更轻松地创建实体变量?

编辑:我怀疑我对第一种和第二种情况的含义有些困惑。我试图在下图中解释它。

组件图

注意各个状态与实体之间的关系。在第一种情况下,会在将AI组件放入实体之前对其进行预先构建。设计人员只能从程序员提供的一组独特的AIComponent中进行选择。第二种情况具有与其他组件相同级别的不同状态。设计人员现在可以创建具有唯一AI的实体,而无需程序员的干预。

问题是,这是在基于组件的实体中构建AI的仅有的两个选择吗?如果是的话,什么将提供最大的灵活性?


我认为一个好的答案将取决于您要在哪里强制执行动作的排他性。如果您希望它位于对象本身中,则设计与通过拖放界面强制执行相比会大不相同(此状态已经具有移动动作,因此不能再具有其他动作,此状态转换容器已经包含基于时间的结束状态等)。
詹姆斯,

2不是可行的选择。
郊狼

Answers:


6

如果您确实打算拥有更多您现在无法想象的敌人或玩家,那么您绝对应该将其分解。第二点要描述的基本上是状态模式

我想我同意格雷戈里(Gregory)的观点,即您不应有独立的站立和行走状态组件。它只是速度为0的运动分量。另一方面,如果您有无法运动的对象,则必须将其拆分,或者只是将某种布尔限制置于运动状态以防止速度为非零。

对于玩家而言,我认为不需要完全分开。除了添加输入组件外,它仍然可以使用所有其他组件。该组件驱动状态之间的转换,而在敌人中,它由默认的AI控制,或者由您的敌人设计人员可以从中选择的不同AI子类控制。

编辑:实际上,对于静止的敌人,而不是限制运动组件,只需给他们一个静止的AI组件,它永远不会选择移动它们。


状态模式是否暗示第一种情况?这导致单个AIComponent实现包含不同状态对象的状态机。我对第二个选项的意思是WalkComponent和SwingComponent与RenderComponent和PhysicsComponent具有相同的类型。

@ghostonline就这个想法而言,有点。在实施中,并非如此。AIComponent将是独立的,如第二个图中所示。它不会包含其他组件。对于第二种情况,更重要的问题是,如果设计人员只是在没有程序员的情况下选择组件,那么实体如何知道何时更改状态?不同的状态意味着不同的状态转换-仍然需要指定这些状态转换。
Tesserex 2011年

您的意思是向图2中的实体添加AIComponent,它将控制Stand / Walk / Swing-Component吗?我的想法是组件在某些条件下会发送阻止或激活信号。例如,SwingComponent将发出通用信号,例如在开始挥杆时发出“ bound_feet”信号,在结束挥杆时发出“ release_feet”。WalkComponent将根据这些信号禁用并启用自身。由于“状态转换”封装在组件本身中,因此设计人员将不需要程序员将组件连接在一起。

@ghostonline对于具有固定规则(例如“不能边走边走”)的东西来说,这很好用,但是站立和走动之间的过渡又如何呢?如果站立在控制之下,怎么会知道走路呢?站立式逻辑可能想要选择步行还是摇摆,这受完全缺乏步行能力的影响-在这种情况下,它应该始终选择摇摆。但是我确实认为您走在正确的道路上。
Tesserex 2011年

2

我至少要保留Player AI(或我称为Player Controller)作为其自己的组件。在大多数游戏中,玩家与NPC的根本区别是,除了基本要素(如生命值)外,您无法一概而论。

对于NPC,我将StandComponent和WalkComponent视为同一事物的各个方面。您是否将拥有一个没有StandComponent的WalkComponent?我对此表示怀疑。同样,RunComponent只是一个具有较高速度和不同动画的WalkComponent。我可以看到拥有一个NPCMovementComponent和一个单独的NPCSwordFighterComponent的价值,但是即使那样对我来说也感觉过度设计。


我不会把NPC运动和玩家运动分开那么多。可以肯定地共享驱动动画和物理的运动动作;选择不同动作或过渡的方式(玩家在AI为... AI时接受输入)。我同意您有一个PlayerController,但您也有一个AIController,两者都可以使用Movement Components / Swing Components来完成实际的动画/物理工作。
homebrew

真正。我假设所有移动的对象都有一个处理其运动的PhysicsComponent或MovementComponent,并且PlayerController和AIController将使用该对象来处理运动。运动绝对应该是一个单独的组成部分,因为可能需要移动的东西没有AI或具有最简单的AI(板条箱或垃圾箱等笨拙的物理对象)。
格雷戈里·艾弗里·威尔

2

首先,我将创建一个State组件,然后创建一个状态机来处理转换。使其具有足够的通用性,以便您可以将其用于播放器和AI。这将确保AI遵循相同的规则,并且与AI状态相比,当您更改玩家状态的工作方式时,您不必更改逻辑。

有限状态机C ++

上面有一个c ++状态机的具体示例,玩家和AI都可以使用它。


1

您需要的是一个处理角色移动(玩家和NPC)的组件。AI组件或玩家组件将向该运动组件发送命令,并将检查是否可以启动该动作。这会将您的运动约束封装到一个组件中。您的AI代码和玩家代码不必知道如何执行摆剑。AI将具有内部状态,例如空闲,攻击,逃跑。


1
TYPO:“这将收到......” 什么从AI部件?
2012年
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.