c++ - 关于纯 ECS(实体组件系统)和更新系统的问题

标签 c++ architecture game-engine game-development entity-component-system

我已经写了一个 ECS,但我对更新阶段有一些疑问。 (在系统中)
我已经阅读了很多文章,但没有找到对此类问题的引用。

为了从 ECS 中受益(例如缓存友好),它们有以下要求:

  • 实体必须只是一个 ID。
  • 组件必须是纯数据(没有逻辑的结构)。
  • 系统包含逻辑并更新组件。
  • 系统之间没有交互(而是系统通过
    向实体添加“标签”组件)。

  • 因此,每个系统中应用的逻辑都很好,并且在它们不是“用户代码”时都可以正常工作。
    但是,当我们处理用户代码时(例如,用户可以将 C++ 代码附加到对象(如 Unity、Unreal)),问题就来了:

  • 因为,组件只包含数据,所以当用户修改
    本地位置,世界位置不更新(世界位置
    将在转换系统处理每个
    变换组件。所以如果用户在之后询问世界位置
    修改它的本地位置,它将获得以前的世界位置
    而不是实际的。
  • 当一个实体被移除时,它的 child 必须被移除。由于
    组件只包含数据而不包含逻辑,子组件将
    不会被删除(它将在下一次父系统更新中)。所以我们
    有一些“延迟”( children 仍然可以访问,但将
    在下一次父系统更新中删除)。
  • 假设我们有实体 A、B、C。B 是 A 的 child 。在
    用户代码(实体附加的c++代码),用户设置父级
    B 有 C,然后删除实体 A。当父系统将
    更新,它会检测到A已被删除,(它也可以检测到
    实体 A 的父级已更改)但系统如何知道
    如果在实体 B 的父级更改后实体 A 已被移除
    还是以前?

  • 在组件中添加逻辑将破坏纯 ECS 的优势(以缓存友好的方式对所有相同的组件执行相同的操作),因此恕我直言,这不是一个解决方案。

    有人有解决方案吗?我想知道您如何处理 ECS 实现中的此类问题。

    谢谢!

    最佳答案

    我和你有同样的问题。
    阅读后我模拟了我的解决方案(这是必须诚实阅读的):
    Gamasutra: Syncing a data-oriented ECS with a stateful external system
    一个可能的解决方案是设置一些关于读写组件的规则。
    我遵循从组件数据中读取总是可以的规则,但是如果您必须将数据写入外部系统内的组件(它不是组件接口(interface)系统的一部分),您必须始终使用转换系统功能。
    例如:
    有一个像这样的转换组件:

    struct transform {
        glm::vec2 position = glm::vec2(0);
        glm::vec2 scale = glm::vec2(1);
        float rot_radians = 0.0f;
        glm::mat3 ltp = glm::mat3(1);
        glm::mat3 ltw = glm::mat3(1);
        entt::entity parent = entt::null;
        std::vector<entt::entity> children;
    };
    
    我将定义一些系统来对其进行更改,如下所示:
    void set_position(entt::registry& r, entt::entity e, glm::vec2 position);
    void set_rotation(entt::registry& r, entt::entity e, float rot_radians);
    void set_scale(entt::registry& r, entt::entity e, glm::vec2 scale);
    void set_parent(entt::registry& r, entt::entity to, entt::entity parent = entt::null);
    
    在这些函数中,您可以自由地读取/写入转换组件数据。
    我使用 ECS 的次数越多,我就越倾向于认为自己是在用 C 编程。你拥有可以更改这些数据的数据和函数。当然,您可以直接更改组件数据,但我意识到花时间试图避免这种情况是不值得的,如果您在更新数据后需要更多东西的组件中进行操作,这只是一个错误或糟糕的编程。

    关于c++ - 关于纯 ECS(实体组件系统)和更新系统的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59787456/

    相关文章:

    java - 如何在java中的窗口上显示48X48像素图像的12X12网格

    ios - iPhone日历导航 Controller

    c++ - C++稳定时钟返回0时间过去了,有时候吗?

    c++ - Tribonacci系列

    c++ - 比较次数和项目移动次数

    php - 知道图片上传网站如何保存图片吗?

    .net - Web 上下文中静态类的生命周期

    architecture - SceneKit 游戏架构

    Java隐藏方法

    c++ - 是否有必要为没有动态资源的类实现 move 构造函数?