1

我有一个渲染系统,它遍历所有 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 中,实体类似于演员,但我发现我完全错了。

例如,您如何组织您的实体以允许使用我之前提到的用例?一个实体应该代表什么?

可能的解决方案:

  1. 永远不要使用在同一实体中创建相同 MeshDrawData 的 SpriteComponent 和 LineComponent 创建实体..(明显但容易出错)
  2. 为每个 SpriteComponent 和/或 LineComponent 创建一个子实体,并将它们添加到各自的子实体。这会起作用,但它会使实体层次结构树变长..不确定它是否更容易出错。...
4

1 回答 1

1

1:1 Entity:Component是一个无聊的限制,也是大多数ECS引擎的一个很好的限制。

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

  1. 默认禁止:: 游戏引擎会在你的第二种情况下抛出 assert-fail 。

  2. 添加检查,例如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 ...
    }
    
  3. 拆分实体添加一对多关系:: 适用于过于复杂的实体。

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

    3.2特定 1:N 关系的完整系统。
    子关系系统的类型应该非常具体
    例如1:N Collider-Sprite,not 1:N entity-entity

在我的游戏中,我以大约 60:30:10(9:1) 的比例混合它们。它运作良好。
如果它开始变得一团糟——使用工厂模式来封装它。

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

于 2020-02-09T03:28:04.447 回答