Flecs is a fast and lightweight Entity Component System with a focus on high performance game development (join the Discord!). Highlights of the framework are:
- Fast to compile & integrate in any project with zero-dependency core that is written entirely in C99
- Provides (SoA) access to raw component arrays for optimal cache efficiency and vectorization
- Archetype-storage with unique graph-based design enables high performance entity mutations
- Flexible API primitives allow for efficient implementation of prefabs, runtime tags and entity graphs
- Supports advanced queries that are entirely evaluated offline to eliminate searching from the main loop
- Lockless threading design allows for efficient execution of systems on multiple threads
- A dashboard module for tracking application metrics (see below for repository link):
ECS (Entity Component System) is a design pattern used in games and simulations that produces fast and reusable code. Dynamic composition is a first-class citizen in ECS, and there is a strict separation between data and behavior. A framework is an Entity Component System if it:
- Has entities that are unique identifiers
- Has components that are plain data types
- Has systems which are behavior matched with entities based on their components
See Docsforge for a more readable version of the documentation.
This is a simple flecs example in the C99 API:
typedef struct {
float x;
float y;
} Position, Velocity;
void Move(ecs_iter_t *it) {
Position *p = ecs_column(it, Position, 1);
Velocity *v = ecs_column(it, Velocity, 2);
for (int i = 0; i < it.count; i ++) {
p[i].x += v[i].x * it->delta_time;
p[i].y += v[i].y * it->delta_time;
printf("Entity %s moved!\n", ecs_get_name(it->world, it->entities[i]));
}
}
int main(int argc, char *argv[]) {
ecs_world_t *ecs = ecs_init();
ECS_COMPONENT(ecs, Position);
ECS_COMPONENT(ecs, Velocity);
ECS_SYSTEM(ecs, Move, EcsOnUpdate, Position, [in] Velocity);
ecs_entity_t e = ecs_set(ecs, 0, EcsName, {"MyEntity"});
ecs_set(ecs, e, Position, {0, 0});
ecs_set(ecs, e, Velocity, {1, 1});
while (ecs_progress(ecs, 0)) { }
}
Here is the same example but in the C++11 API:
struct Position {
float x;
float y;
};
struct Velocity {
float x;
float y;
};
int main(int argc, char *argv[]) {
flecs::world ecs;
ecs.system<Position, const Velocity>()
.each([](flecs::entity e, Position& p, const Velocity& v) {
p.x += v.x * e.delta_time();
p.y += v.y * e.delta_time();
std::cout << "Entity " << e.name() << " moved!" << std::endl;
});
ecs.entity("MyEntity")
.set<Position>({0, 0})
.set<Velocity>({1, 1});
while (ecs.progress()) { }
}
The easiest way to add Flecs to a project is to add flecs.c and flecs.h to your source code. These files can be added to both C and C++ projects (the C++ API is embedded in flecs.h). Alternatively you can also build Flecs as a library by using the cmake, meson, bazel or bake buildfiles.
The Flecs source has a modular design which makes it easy to strip out code you don't need. At its core, Flecs is a minimalistic ECS library with a lot of optional features that you can choose to include or not. This section of the manual describes how to customize which features to include.
To ensure stability of Flecs, the code is thoroughly tested on every commit:
- 40.000 lines of test code, for 18.000 lines of framework code
- More than 1600 testcases
- Over 90% code coverage
The code is validated on the following platforms/compilers:
- Windows
- msvc
- Ubuntu
- gcc 7, 8, 9, 10
- clang 8, 9
- MacOS
- gcc 10
- clang 9
The framework code and example code is compiled warning free on all platforms with the strictest warning settings. A sanitized build is ran on each commit to test for memory corruption and undefined behavior.
Performance is tracked on a per-release basis, with the results for the latest release published here: https://github.com/SanderMertens/ecs_benchmark
The following modules are available in flecs-hub. Note that modules are mostly intended as example code, and their APIs may change at any point in time.
Module | Description |
---|---|
flecs.meta | Reflection for Flecs components |
flecs.json | JSON serializer for Flecs components |
flecs.rest | A REST interface for introspecting & editing entities |
flecs.player | Play, stop and pause simulations |
flecs.monitor | Web-based monitoring of statistics |
flecs.dash | Web-based dashboard for remote monitoring and debugging of Flecs apps |
flecs.components.input | Components that describe keyboard and mouse input |
flecs.components.transform | Components that describe position, rotation and scale |
flecs.components.physics | Components that describe physics and movement |
flecs.components.geometry | Components that describe geometry |
flecs.components.graphics | Components used for computer graphics |
flecs.components.gui | Components used to describe GUI components |
flecs.components.http | Components describing an HTTP server |
flecs.systems.transform | Hierarchical transforms for scene graphs |
flecs.systems.sdl2 | SDL window creation & input management |
flecs.systems.sokol | Sokol-based renderer |
flecs.systems.civetweb | A civetweb-based implementation of flecs.components.http |
Supporting Flecs goes a long way towards keeping the project going and the community alive! If you like the project, consider:
- Giving it a star
- Becoming a sponsor: https://github.com/sponsors/SanderMertens
Thanks in advance!