c++ ecs:EnTT

这是个c++17的库,在确定ios 和 android都可以使用c++17以后,我也决定使用c++17. 于是entt也可以纳入使用范围。 这是在比较了 entt和它的竞品之后,觉得entt在总体上表现不错,成熟、稳定、性能优异。

  1. entt是个头文件库,不需要编译,只需要导入所需的头文件即可,开箱即用。
  2. entt在多个os的编译器上都通过了编译,在android和ios也通过编译。
  3. 有现成的产品在使用它,比如《我的世界》
  4. 我们可以在遍历的同时添加、删除实体、组件,很方便。
  5. 性能对比
    https://github.com/abeimler/ecs_benchmark

官方文档:

  1. https://skypjack.github.io/entt/
  2. https://github.com/skypjack/entt/wiki
    右边列表即是速成教程。

官方代码库

https://github.com/skypjack/entt

官方helloworld

#include <entt/entt.hpp>
#include <cstdint>

struct position {
    float x;
    float y;
};

struct velocity {
    float dx;
    float dy;
};

void update(entt::registry &registry) {
    auto view = registry.view<position, velocity>();

    for(auto entity: view) {
        // gets only the components that are going to be used ...

        auto &vel = view.get<velocity>(entity);

        vel.dx = 0.;
        vel.dy = 0.;

        // ...
    }
}

void update(std::uint64_t dt, entt::registry &registry) {
    registry.view<position, velocity>().each([dt](auto &pos, auto &vel) {
        // gets all the components of the view at once ...

        pos.x += vel.dx * dt;
        pos.y += vel.dy * dt;

        // ...
    });
}

int main() {
    entt::registry registry;
    std::uint64_t dt = 16;

    for(auto i = 0; i < 10; ++i) {
        auto entity = registry.create();
        registry.emplace<position>(entity, i * 1.f, i * 1.f);
        if(i % 2 == 0) { registry.emplace<velocity>(entity, i * .1f, i * .1f); }
    }

    update(dt, registry);
    update(registry);

    // ...
}

后记

花了两天时间,把既有代码切换到了entt,也没有太大不同,主要就是熟悉api,改变对象的组织方式。它对组件的要求比较简单,有0参数构造函数、可移动即可。

但是在实体和组件的筛选上,它提供了不少灵活性。

关于性能

虽然EnTT声称性能很好,也可能比别的ecs框架性能稍好,但是当我看到获取组件需要传递entity的时候,就开始担心性能了:获取组件需要id做参数,这意味着至少是一次查询,就算是用hash表,性能也会差不少。

于是我就简单测试了一下,然后和通过偏移获取组件想对比,都是debug编译:
EnTT的getComponent,每秒执行110万次;
通过偏移则快多了,每秒可以获取3000多万次;

如果用在客户端,EnTT可以了,算是很快。要是用到服务器上,还差点火候。我还是愿意直接写对象,提升性能。毕竟基础开销越低,留给游戏逻辑的计算资源就越多。

同时,如果声称性能好的库,都给出一个基础对比性能测试就好了,这样,看一眼就知道性能好不好,不然,还是得自己上去测试。

发表评论

电子邮件地址不会被公开。 必填项已用*标注

− 3 = 1