【问题标题】:Inheritance in an Entity Component System实体组件系统中的继承
【发布时间】:2016-09-01 00:12:48
【问题描述】:

我在网上阅读的大多数关于实体组件系统的材料似乎都表明它被用来避免使用继承。但是我想知道的是,在ECS旁边继续使用继承是否可行?

假设我在引擎中有特定数量的实体,它们将具有大部分相同的功能。例如,能够移动的实体。那么创建一个添加必要组件的MovableEntity 对象是否可行?

public class MovableEntity extends Entity {
    public MovableEntity(int x, int y) {
        addComponent(new PositionComponent(x, y));
        addComponent(new VelocityComponent());
        ...
    }
}

【问题讨论】:

  • 是的,您可以这样做,但是现在您将继承与基于组件的设计混合在一起,这并不一致。你必须判断一致性对你来说是否值得。你只是想实现代码重用吗?如果是这样,您总是可以将“addComponent”行提取到全局静态函数中。

标签: oop inheritance entity entity-component-system


【解决方案1】:

如果您不需要在实体中动态添加/删除组件,则可以使用继承来定义实体(在具有多重继承的语言中)。考虑以下来自 Evolve Your Hierarchy 的 ECS 示例:

您的组件将对应于类:

  • 班级职位
  • 班级运动
  • ...

您的实体将对应于类:

  • 类外星人:位置、运动、渲染……
  • 类玩家:位置、运动、物理……
  • ...

【讨论】:

    【解决方案2】:

    虽然不是标准的,但我发现这种做法非常有用。想象一个战士有HP、攻击和防御的游戏。您可以编写一个接受枚举和值的 stat 组件。另一种方法是拥有一个包含其他实体的组件,并使每个 stat 本身成为具有值和类型组件的实体。我尝试了这两种方法,但我不喜欢早期的结果。 (后者运行良好,但确实很复杂,但它确实严格遵守 ECS 设计)

    最后我把每一个都做成了一个继承自Component的StatComponent。这意味着我可以执行所有统计数据通用的操作,这非常方便。诀窍是让每一点 OOP 都陷入泡沫中。只要它是自包含的,我就看不到任何重大问题。

    【讨论】:

      【解决方案3】:

      我希望你不要介意我的直率意见,但以你的做法,我认为这是个坏主意。

      首先,您是否只是为了更容易地构造它们而定义新的组件类型?如果是这样,您可以像这样使用:

      Entity movable_entity(int x, int y)
      {
          Entity new_entity = ...;
          new_entity.addComponent(new PositionComponent(x, y));
          new_entity.addComponent(new VelocityComponent());
          ...
          return new_entity;
      }
      

      这似乎只是一种风格上的差异,但当它不涉及继承时,它表现出更松散的耦合。

      其次,如果您要实际向 MovableEntity 添加 Entity 没有的新状态,这使得您的实体不再统一大小,我们无法再有效地连续表示所有实体具有直接随机访问的内存,并且它们也可能容易进行对象切片(例如:当希望克隆 MoveableEntity 时,从可移动的对象中克隆 Entity)。

      所以至少对于实体来说,我真的认为你最好不要扩展它们。我可以看到更多组件类型继承的用例,尽管我仍然建议不要这样做,因为 ECS 在访问组件方面非常灵活,不需要通过组件基类型的多态性。如果您想在另一个组件中重用一个组件的数据字段,您可以只使用组合。

      继承向 ECS 添加了一种竞争类型的模型,这种模型并不能很好地运行,除非您这样做是为了更容易地使用一组特定的组件构建特定类型的实体,这又一次可以只需一个简单的函数即可完成,而无需引入全新的实体类型。

      【讨论】:

      • 这是解决我的问题的合适方法。感谢您的意见!
      猜你喜欢
      • 2018-01-05
      • 1970-01-01
      • 1970-01-01
      • 2016-01-23
      • 2014-07-06
      • 1970-01-01
      • 2016-03-31
      • 2016-11-05
      • 1970-01-01
      相关资源
      最近更新 更多