C++ 如何在ECS模型中组织实体?

C++ 如何在ECS模型中组织实体?,c++,entity,game-engine,entity-component-system,C++,Entity,Game Engine,Entity Component System,我有一个渲染系统,它迭代所有MeshDrawData组件,并对它们进行批处理和绘制。我的ECS实施只允许每个实体使用一种类型的组件 现在我想代表“运动员”乒乓球拍。我的OOP思维方式是这样的: Pseudocode: auto e = createEntity(); createSpriteComponent(e,...); // this creates a MeshDrawData internally for e entity. createColliderComponent(e,...)

我有一个渲染系统,它迭代所有MeshDrawData组件,并对它们进行批处理和绘制。我的ECS实施只允许每个实体使用一种类型的组件

现在我想代表“运动员”乒乓球拍。我的OOP思维方式是这样的:

Pseudocode:
auto e = createEntity();
createSpriteComponent(e,...); // this creates a MeshDrawData internally for e entity.
createColliderComponent(e,...);
这很好,但假设现在我也想渲染一条线。 如果我这样做:

Pseudocode:
auto e = createEntity();
createSpriteComponent(e,...); // this creates a MeshDrawData internally for the e entity.
createColliderComponent(e,...);
createLineComponent(e,...); // this creates a MeshDrawData internally for the e entity
在这里你可以看到问题。。我为实体e创建了两个MeshDrawData组件

鉴于我不真实的引擎背景,我创建了一个演员并向其添加组件。我一直认为ECS中的实体类似于演员,但我发现我完全错了

您如何组织您的实体,例如允许使用我前面提到的用例?实体究竟应该代表什么

可能的解决办法:

  • 切勿使用在同一图元中创建相同MeshDrawData的SpriteComponent和LineComponent创建图元。。(明显但容易出错)
  • 为每个SpriteComponent和/或LineComponent创建子图元,并将其添加到相应的子图元中。这会起作用,但会生成较长的实体层次结构树。。不确定它是否更容易出错。

  • 1:1实体:组件
    是一个无聊的限制,但也是大多数ECS引擎的一个很好的限制

    为了解决这些问题,我通常会执行以下操作之一:-

  • 默认情况下禁止它::在第二种情况下,游戏引擎将抛出assert fail

  • 添加检查例如,在
    createLineComponent
    中检查
    MeshDrawData
    是否已存在,并执行一些自定义操作

    我主要是这样做的:-

    void createLineComponent(Entity e){
        auto meshComponent=engine->addJustInCase<MeshDrawData>(e);
        //^ if the component exists - just request the component, if not, create it
        meshComponent->setFormat ...
    }
    
    void createLineComponent(实体e){
    auto meshComponent=发动机->添加案例(e);
    //^如果组件存在-只需请求组件,如果不存在,则创建它
    网格组件->设置格式。。。
    }
    
  • 拆分实体并添加一对多关系::适用于过于复杂的实体

    3.1保持简单-父缓存子实体作为其字段

    3.2特定1:N关系的完整系统
    子关系系统的类型应非常具体 e、 g.
    1:N碰撞器精灵
    ,而不是
    1:N实体

  • 在我的游戏中,我将它们混合在60:30:10(9:1)左右。它工作得很好。
    如果它开始变得一团糟-使用工厂模式来封装它


    如果有人有任何(更好的)想法,请回答。我也想听听。

    谢谢你的回答。现在我在做你的方法。我用添加的最新组件覆盖MeshDrawData,该组件需要它。我不会选择这个作为正确答案,看看是否有人有其他想法。@FrameBuffer不错。如果您发现任何有用的东西或使用此方法完成游戏,请让我知道。:)我想得更多,我的结论是,你可以决定把你所有的状态都放在ecs中,或者与系统共享。我现在的方法是将所有状态放在组件中,只是为了保持一致。考虑到我决定为实体拥有的每个不同的“渲染器组件”创建一个子级。并在实体的“渲染器组件”中保存对实体的引用,以防您必须访问它。@FrameBuffer只是为了检查我的理解。你…吗。。。(1) 通过增强ECS核心引擎,允许1个实体拥有>1个
    渲染器组件
    ?或者(2)减少/减少渲染器组件,使其不再是ECS组件,并手动管理它?还是别的什么。。。我只做了一次。它位于我的物理引擎(
    流形组件
    )的性能关键区域。我“在一个实体中,每种类型只有一个组件”。从体系结构的角度来看,我所改变的是,带有线条渲染器和喷绘器的实体对我来说没有意义,因此我结束了您的第一(1)种方法(因为这是错误的)。例如,精灵是具有变换和精灵(将创建和处理自己的MeshDrawData)的实体。因此,具有精灵的角色将由具有子实体(精灵)的实体(玩家)表示。如果玩家想要画一条线,该线是另一个实体(transform,LineRenderer->MeshDrawData)