在游戏子系统中注册游戏对象组件? (基于组件的游戏对象设计)

时间:2010-10-18 10:59:23

标签: c++ architecture components subsystem

我正在创建一个component-based game object system。一些提示:

  1. GameObject只是Components
  2. 的列表
  3. GameSubsystems。例如,渲染,物理等。每个GameSubsystem都包含指向某些Components的指针。 GameSubsystem是一个非常强大而灵活的抽象:它代表了游戏世界的任何片段(或方面)。
  4. 需要在Components中注册GameSubsystems的机制(创建和编写GameObject时)。有 4种方法


    • 1:Chain of responsibility模式。每个Component都会提供GameSubsystemGameSubsystem做出Components注册(以及如何组织它们)的决定。例如,GameSubsystemRender可以注册可渲染组件。

    亲。 Components对如何使用它们一无所知。低耦合。 A. 我们可以添加新的GameSubsystem。例如,让我们添加注册所有ComponentTitle的GameSubsystemTitles,并保证每个标题都是唯一的,并提供按标题查询对象的接口。当然,在这种情况下,ComponentTitle不应该被重写或继承。 B. 我们可以重新组织现有的GameSubsystems。例如,GameSubsystemAudio,GameSubsystemRender,GameSubsystemParticleEmmiter可以合并到GameSubsystemSpatial中(将所有音频,emmiter,render Components放在同一层次结构中并使用父相对变换)。

    CON。每一次检查。效率很低。

    CON。 Subsystems了解Components


    • 2:每个Subsystem搜索特定类型的Components

    亲。比Approach 1更好的表现。

    CON。 Subsystems仍然了解Components


    • 3:ComponentGameSubsystem(s)中注册。我们在编译时知道有一个GameSubsystemRenderer,所以让我们的ComponentImageRender会调用类似GameSubsystemRenderer :: register(ComponentRenderBase *)的东西。
      Observer模式。 Component订阅了“更新”事件(由GameSubsystem(s)发送)。

    亲。性能。没有不必要的检查,如Approach 1Approach 2

    CON。 ComponentsGameSubsystems非常吻合。


    • 4:Mediator模式。 GameState(包含GameSubsystems)可以实现registerComponent(Component *)。

    亲。 ComponentsGameSubystems对彼此一无所知。

    CON。在C ++中,它看起来像丑陋和慢速的typeid-switch。


    问题: 哪种方法更好,主要用于基于组件的设计?实践说什么?关于Approach 4的实施(数据驱动)的任何建议?

    谢谢。

2 个答案:

答案 0 :(得分:2)

投票支持第三种方法。

我目前正致力于基于组件的游戏对象系统,我清楚地看到了这种方法的一些额外优势:

  • 组件越来越自给自足,因为它只依赖于一组可用的子系统(我认为这个组合在你的项目中是固定的)。

  • 数据驱动设计更适用。理想情况下,您可以通过这种方式设计一个系统,其中组件完全按照数据而非C ++定义。


编辑:我在研究CBGOS时考虑过的一个特性。有时可以方便地设计和构建无子系统无源组件。当你想到这一点时,第四种方法是唯一的方法。

答案 1 :(得分:1)

我的方法是在每个子系统中实现代理模式。由于每个子系统仅对每个实体可能包含的总组件的子集感兴趣,因此代理仅存储指向系统所关心的组件的指针,例如,运动系统仅关注位置和速度,因此它需要存储的代理两个指针,到那些组件。如果实体缺少其中的一个或多个,则子系统将忽略它。如果两个组件都存在,则创建代理节点并将其添加到内部集合。代理还可以存储实体的唯一标识符值,以便在必要时可以在每个子系统的固定时间内添加/删除代理。

以这种方式,如果要求从引擎中删除实体,则可以将包含实体ID的单个消息发送到每个子系统。然后可以独立地从每个子系统集合中删除代理。