richardbiely / gaia-ecs

A simple and powerful entity component system (ECS) written in C++17
MIT License
80 stars 3 forks source link

Improve how systems are defined and organized #7

Open richardbiely opened 1 year ago

richardbiely commented 1 year ago

Current version: System is a virtual class with overridden member functions. Systems are managed by SystemManager. They are not connected. On the outside this looks very similar to what DOTS does.

class PositionSystem final: public ecs::System {
  static constexpr float dt = 0.01f;
    ecs::Query m_q;

public:
    void OnCreated() override {
        m_q = world().query().all<Position&, Velocity>();
    }

    void OnUpdate() override {
        m_q.each([](Position& p, const Velocity& v) {
            p.x += v.x * dt;
            p.y += v.y * dt;
            p.z += v.z * dt;
        });
    }
};

ecs::SystemManager sm(w);
sm.add<PositionSystem>();
sm.add<OtherSystem>();
...
sm.update(); // run all systems once

Proposed version: Systems are entities with a System component attached. Maybe even inheriting from Query (so they are cached). This gives us a lot of flexibility. Enabling the system = enabling the entity. Systems can be queried (e.g. disable all systems that do this-and-that easily). Organized into stages. Stages can be user defined, probably implemented as components. In order for the grouping to work correctly, relationship support would come handy.

auto s = w.system()
        .stage<LateUpdate>() // optional, if not used, the system goes to the default stage
    .all<Position&, Velocity>()
    .any<Rotation>()
    .OnCreated([](ecs::Query& q) { // event when created
    })
    .OnStopped([](ecs::Query& q) { // event when stopped
        ...
    })
       // other events
        ...
       // function to run every update (equivalent to ecs::query::each)
    .OnUpdate([](Position& p, const Velocity& v) {
        p.x += v.x * dt;
        p.y += v.y * dt;
        p.z += v.z * dt;
    })
    .commit();

Necessary: