Entity Component System

A complete ECS for C and C++.

Archetype storage, persistent queries, scheduled systems, relations, reflection, and tooling in one embeddable library.

Storage and execution in one ECS.

SIECS manages component data and the systems that process it. Relations, events, resources, and metadata remain part of the same world.

Systems and scheduling

Bind a query to a named callback and place it in a phase. One call to ecs_progress() runs the schedule.

ecs::system("Move").phase(EcsOnUpdate)

Relations and inheritance

Build hierarchies with ChildOf, share component defaults with IsA, and attach custom relation targets.

child.child_of(parent)

Resources and events

Keep singleton state in typed resources. Observers react to component changes and application events.

ecs::set_resource(Time{ .dt = 0.016f })

Reflection and tooling

Reflect component fields for JSON serialization and inspect live entities and schemas through the optional REST explorer.

GET /entities

Queries resolve tables before iteration.

Persistent queries retain their matching archetype tables. Iterators expose the requested component columns one batch at a time.

Query ecs_inout(Position), ecs_in(Velocity)
System Move in EcsOnUpdate
Batch Position*, const Velocity*, count

The same ECS from C or C++.

C describes terms and reads batch fields directly. C++ infers access from callback parameter types. Both interfaces use the same runtime.

ecs_query_id_t moving = ecs_query({
    .terms = {
        ecs_inout(Position),
        ecs_in(Velocity),
    },
});

ecs_iter_t it = ecs_query_iter(moving);
while (ecs_iter_next(&it)) {
    Position *positions = ecs_field(&it, 0);
    const Velocity *velocities = ecs_field(&it, 1);

    for (uint32_t i = 0; i < it.count; i++) {
        positions[i].x += velocities[i].x;
        positions[i].y += velocities[i].y;
    }
}

Compile SIECS with the application.

The standalone distribution is siecs.h and siecs.c: one public header and one C source file.

cc -std=c23 -I. main.c siecs.c -pthread -o my_app

Continue with a working example.

Compile a small program first, then move into storage, API, and game-loop design.

Start with the quick start.

Add the two files, create an entity, and run the first system.

Read the quick start