Oop 实体组件系统中的继承
我在网上读到的大多数关于实体组件系统的资料似乎都表明,它是用来避免使用继承的。但我想知道的是,在ECS旁边继续使用继承是否可行 假设我在一个引擎中有特定数量的实体,这些实体将具有基本相同的功能。例如,可以移动的实体。然后可以创建一个添加必要组件的Oop 实体组件系统中的继承,oop,inheritance,entity,entity-component-system,Oop,Inheritance,Entity,Entity Component System,我在网上读到的大多数关于实体组件系统的资料似乎都表明,它是用来避免使用继承的。但我想知道的是,在ECS旁边继续使用继承是否可行 假设我在一个引擎中有特定数量的实体,这些实体将具有基本相同的功能。例如,可以移动的实体。然后可以创建一个添加必要组件的MovableEntity对象吗 public class MovableEntity extends Entity { public MovableEntity(int x, int y) { addComponent(new
MovableEntity
对象吗
public class MovableEntity extends Entity {
public MovableEntity(int x, int y) {
addComponent(new PositionComponent(x, y));
addComponent(new VelocityComponent());
...
}
}
如果不需要在实体中动态添加/删除组件,则可以使用继承定义实体(在具有多重继承的语言中)。从以下例子考虑ECS: 您的组件将对应于类:
- 阶级地位
- 阶级运动
- 类外星人:位置、移动、渲染
- 职业选手:位置、动作、物理
- 虽然不是标准做法,但我发现这种做法非常有用。想象一个游戏,一个战士有生命,攻击和防御。您可以编写一个接受枚举和值的stat组件。另一种方法是使用一个包含其他实体的组件,并使每个stat本身成为一个具有值和类型组件的实体。我尝试了这两种方法,但我不喜欢早期的结果。(后者工作得很好,但确实很复杂,但它确实严格遵循ECS设计)
最后,我把每一个都做成了一个StatComponent,它继承了这个组件。这意味着我可以执行所有统计数据通用的操作,这非常方便。诀窍是让你的每一点OOP都粘在一个泡泡里。只要它是独立的,我就看不到任何重大问题 我希望你不要介意我直截了当的意见,但就你这样做,我认为这是个坏主意 首先,您定义新的组件类型只是为了更容易地构造它们吗?如果是这样的话,您可以使用:
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;
}
这看起来可能只是一种风格上的差异,但在不涉及继承的情况下,它表现出更松散的耦合
第二,如果您要向实体
没有的可移动实体
添加新状态,这使得您的实体不再具有统一的大小,我们无法再通过直接随机访问有效地在内存中连续表示所有实体,而且他们也可能倾向于对象切片(例如:当想要克隆可移动实体时,从可移动实体中克隆实体
)
所以,至少对于实体,我真的认为最好不要扩展它们。我可以看到更多关于组件类型继承的用例,尽管我仍然建议不要这样做,因为ECS在访问组件的方式上非常灵活,因此不需要通过组件基类型进行多态性。如果您想在另一个组件中重用一个组件的数据字段,则可以使用组合
继承为ECS添加了一种相互竞争的模型,这种模型并不那么完美,除非您只是为了更容易地使用一组特定的组件构建一种特定类型的实体,而这些组件也可以通过简单的函数实现,而无需引入一种全新的实体类型。是的,您可以这样做,但现在您将继承与基于组件的设计相混合,这是不一致的。你必须判断一致性对你来说是否值得。您只是想实现代码重用吗?如果是这样的话,您可以将“addComponent”行提取到全局静态函数中。这是解决我的问题的合适方法。谢谢你的意见!