Skip to content

C++ ECS Components and Systems: Benefits and Costs

Separate stores make capability processing explicit but distribute one body's behaviour across passes. We evaluate both effects rather than treating ECS as OOP's inevitable destination.

Map the Same Data

ecs.hpp owns fixed stores keyed by world-issued numbers:

Store Meaning Writer
Positions Live body location Movement
Velocities Movement capability Acceleration
Accelerations Optional velocity change Construction in this example
Lifetimes Optional remaining lifetime Lifetime
Visible set Render participation Construction and cleanup

Position membership defines a live entity. Acceleration requires velocity. Every other key must have a position.

This is a fixed-type teaching implementation, not a generic engine or runtime query language.

Order Remains Behaviour

EcsWorld::step runs acceleration, movement, lifetime, then cleanup, matching earlier worlds.

Acceleration traverses acceleration data and updates velocity. Movement traverses velocities and updates positions. Visibility is absent from both queries.

These are the actual consecutive loops from EcsWorld::step:

1
2
3
4
5
6
7
8
for (const auto& [number, acceleration] : accelerations_) {
    accelerate(velocities_.at(number), acceleration, dt);
    record(number, Stage::acceleration);
}
for (const auto& [number, velocity] : velocities_) {
    move(positions_.at(number), velocity, dt);
    record(number, Stage::movement);
}

The .at calls express required membership. They are not a substitute for validation: construction and cleanup must preserve the relationship so these lookups succeed.

This helps answer “who writes velocity?” Answering “what happens to body 1?” now requires several passes.

Construction and Cleanup Count Too

Adding a component requires validation, store population, observation, and deletion—not just a system.

Spawn validates before publication. If a store allocation fails during construction, partial entries for that number are removed. An issued number may be consumed.

Cleanup removes positions, velocities, accelerations, lifetimes, and visibility together. A forgotten store leaves an orphan even when render output looks correct.

Run the Contract

1
2
3
/tmp/pi-design-main/design_demo ecs
/tmp/pi-design-main/design_tests ecs
/tmp/pi-design-main/design_tests alternatives

The alternatives group compares complete snapshots against other designs. The ECS group checks final movement, execution order, and cleanup of all stores.

Explain the Trade-Off

Task Records Component stores
Find one body's update One advance function Several ordered passes
Locate acceleration writers Capability branch Acceleration pass
Add capability Field, validation, update, observation Store, validation, pass, cleanup, observation
Maintain validity Record invariants Cross-store consistency too

Ordered maps keep this implementation inspectable. ECS does not imply packed storage, faster execution, or lower memory use.

Exercise

List every edit for a future Drag component, including rollback, cleanup, and snapshots. If another store helps no concrete requirement, composition is still reasonable.

Next: specify when structural changes become visible.


Previous: Chapter 5 · Course overview · Next: Chapter 7

Donate