flecs

CI build codecov Discord Chat Try online Documentation

Flecs is a fast and lightweight Entity Component System with a focus on high performance game development and usability (join the Discord!). The highlights of the framework are:

  • Zero dependency C99 core, modern type safe C++11 API, no dependencies on STL types
  • SoA/Archetype storage enables efficient CPU caching/vectorization & direct access to component arrays
  • Automatic component registration across binaries and worlds
  • Runtime creation/deletion of components, tags, queries and systems
  • Optional reflection addons, including JSON (de)serializers & scripting language support APIs
  • Entity relationships (Bob.add(Likes, Alice)) enable creation of entity graphs
  • Fast query engine that supports graph traversal, joins & various operators
  • Builtin support for hierarchies, prefabs and component sharing
  • Transitive relationships ("if Bob lives in San Francisco and San Francisco is in the US, Bob lives in the US")
  • Lockless command buffer implementation enables asynchronous deferring of operations
  • Reactive systems for listening to component add/remove events (amongst others)
  • Organize components & systems in reusable packages with flecs modules
  • Ordered access ("sort by Position") and grouped access ("group by platoon")
  • A dashboard module for visualizing statistics:
Screen Shot 2020-12-02 at 1 28 04 AM

This is a v3 alpha release! All of the usual QA is applied to master, but API changes may occur! For the last stable version, use Flecs v2.4.6.

What is an Entity Component System?

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

Documentation

If you are still learning Flecs, these resources are a good start:

The FAQ is where some of the most asked questions are listed:

The manual and examples come in handy if you're looking for information on specific features:

If you are migrating from Flecs v1 to v2, check the migration guide:

Here is some awesome content provided by the community (thanks everyone! :heart:):

Examples

This is a simple flecs example in the C99 API:

typedef struct {
  float x, y;
} Position, Velocity;

void Move(ecs_iter_t *it) {
  Position *p = ecs_term(it, Position, 1);
  Velocity *v = ecs_term(it, Velocity, 2);
  
  for (int i = 0; i < it->count; i ++) {
    p[i].x += v[i].x;
    p[i].y += v[i].y;
  }
}

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, Velocity);

  ecs_entity_t e = ecs_new_id(ecs);
  ecs_set(ecs, e, Position, {10, 20});
  ecs_set(ecs, e, Velocity, {1, 2});

  ecs_iter_t it = ecs_term_iter(world, &(ecs_term_t) { ecs_id(Position) });
  while (ecs_term_next(&it)) {
    Position *p = ecs_term(&it, Position, 1);
    for (int i = 0; i < it.count; i ++) {
      printf("{%f, %f}\n", p[i].x, p[i].y);
    }
  }

  while (ecs_progress(ecs, 0)) { }
}

This is the same example in the C++11 API:

struct Position {
  float x, y;
};

struct Velocity {
  float x, y;
};

int main(int argc, char *argv[]) {
  flecs::world ecs;

  ecs.system<Position, const Velocity>()
    .each([](Position& p, const Velocity& v) {
      p.x += v.x;
      p.y += v.y;
    });

  auto e = ecs.entity()
    .set([](Position& p, Velocity& v) {
      p = {10, 20};
      v = {1, 2};
    });

  ecs.each([](flecs::entity e, Position& p) {
    std::cout << "{" << p.x << ", " << p.y << "}" << std::endl;
  });
    
  while (ecs.progress()) { }
}

The first C example used macro's to emulate a type-safe layer on top of the underlying generic API. This example shows the C API without macro's:

// Register the Position component
ecs_entity_t pos = ecs_component_init(ecs, &(ecs_component_desc_t){
  .entity.name = "Position",
  .size = sizeof(Position), .alignment = ECS_ALIGNOF(Position)
});

// Register the Velocity component
ecs_entity_t vel = ecs_component_init(ecs, &(ecs_component_desc_t){
  .entity.name = "Velocity",
  .size = sizeof(Velocity), .alignment = ECS_ALIGNOF(Velocity)
});

// Create the Move system
ecs_system_init(ecs, &(ecs_system_desc_t){
  .entity = { .name = "Move", .add = {EcsOnUpdate} },
  .query.filter.terms = {{pos}, {vel, .inout = EcsIn}},
  .callback = Move,
});

// Create entity
ecs_entity_t e = ecs_new_id(ecs);

// Set components
ecs_set_id(ecs, e, pos, sizeof(Position), &(Position){10, 20});
ecs_set_id(ecs, e, vel, sizeof(Velocity), &(Velocity){1, 2});

Building

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.

Custom builds

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.

Software Quality

To ensure stability of Flecs, the code is thoroughly tested on every commit:

  • More than 2400 testcases and 60.000 lines of test code
  • Over 90% code coverage
  • All tests run without memory leaks & memory corruption
  • All examples are compiled warning free

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

API stability

APIs are stable between minor and patch versions, but exceptions are made in these scenarios:

  • The design of an API prevents it from being used without introducing bugs
  • The design of an API is prone to misuse or confusing

The following parts of the API are not stable between patch/minor versions:

  • Anything in include/private
  • The ABI is not guaranteed to be stable, so a recompile of code is required after upgrading

Functions may become deprecated before a major release. To build flecs without deprecated functions, exclude the FLECS_DEPRECATED addon. (see custom builds).

Modules

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.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

Language bindings

Supporting Flecs

Supporting Flecs goes a long way towards keeping the project going and the community alive! If you like the project, consider:

Thanks in advance!