|
|
8 years ago | |
|---|---|---|
| build | 9 years ago | |
| cmake | 8 years ago | |
| deps | 8 years ago | |
| src | 8 years ago | |
| test | 8 years ago | |
| .gitignore | 9 years ago | |
| .travis.yml | 8 years ago | |
| AUTHORS | 9 years ago | |
| CMakeLists.txt | 8 years ago | |
| LICENSE | 9 years ago | |
| README.md | 8 years ago | |
| appveyor.yml | 8 years ago |
EnTT is a header-only, tiny and easy to use Entity-Component System in modern C++.
ECS is an architectural pattern used mostly in game development. For further details:
#include <registry.hpp>
struct Position {
float x;
float y;
};
struct Velocity {
float dx;
float dy;
};
using ECS = entt::DefaultRegistry<Position, Velocity>;
int main() {
ECS ecs;
for(auto i = 0; i < 10; ++i) {
auto entity = ecs.create();
ecs.assign<Position>(entity, i * 1.f, i * 1.f);
if(i % 2 == 0) { ecs.assign<Velocity>(entity, i * .1f, i * .1f); }
}
// single component view
for(auto entity: ecs.view<Position>()) {
auto &position = ecs.get<Position>(entity);
// do whatever you want with position
(void)position;
}
// multi component view
for(auto entity: ecs.view<Position, Velocity>()) {
auto &position = ecs.get<Position>(entity);
auto &velocity = ecs.get<Velocity>(entity);
// do whatever you want with position and velocity
(void)position;
(void)velocity;
}
}
I started working on EnTT because of the wrong reason: my goal was to beat another well known open source ECS in terms of performance.
I did it, of course, but it wasn't much satisfying. Actually it wasn't satisfying at all. The fastest and nothing more, fairly little indeed.
When I realized it, I tried hard to keep intact the great performance and to add all the features I want to see in my ECS at the same time.
Today EnTT is finally what I was looking for: still faster than its rivals, a really good API and an amazing set of features.
As it stands right now, EnTT is just fast enough for my requirements if compared to my first choice (a well known open source ECS that was already amazingly fast).
Here is a comparision (both of them compiled with GCC 7.2.0 on a Dell XPS 13 coming from the late 2014):
| Benchmark | EntityX (experimental/compile_time) | EnTT |
|---|---|---|
| Creating 10M entities | 0.290214s | 0.143111s |
| Destroying 10M entities | 0.104589s | 0.0917096s |
| Iterating over 10M entities, unpacking one component | 0.0165628ss | 1.37e-07ss |
| Iterating over 10M entities, unpacking two components | 0.0137463ss | 0.0052857ss |
| Iterating over 10M entities, unpacking two components, half of the entities have all the components | 0.011949ss | 0.00268133ss |
| Iterating over 10M entities, unpacking two components, one of the entities has all the components | 0.0115935ss | 6.4e-07ss |
| Iterating over 10M entities, unpacking five components | 0.0143905ss | 0.00527808ss |
| Iterating over 10M entities, unpacking ten components | 0.0165853ss | 0.00528096ss |
| Iterating over 10M entities, unpacking ten components, half of the entities have all the components | 0.0169309ss | 0.00327983ss |
| Iterating over 10M entities, unpacking ten components, one of the entities has all the components | 0.0110304ss | 8.11e-07ss |
| Iterating over 50M entities, unpacking one component | 0.0827622ss | 1.65e-07ss |
| Iterating over 50M entities, unpacking two components | 0.0830518ss | 0.0265629ss |
See benchmark.cpp for further details.
Even though EnTT includes its own tests and benchmarks, on Github there exists also a benchmark suite that compares a bunch of different projects, one of which is EnTT.
Of course, I'll try to get out of EnTT more features and better performance anyway in the future, mainly for fun.
If you want to contribute and/or have any suggestion, feel free to make a PR or open an issue to discuss your idea.
To be able to use EnTT, users must provide a full-featured compiler that supports at least C++14.
CMake version 3.2 or later is mandatory to compile the tests, users don't have to install it otherwise.
EnTT is a header-only library. This means that including the registry.hpp header is enough to use it.
It's a matter of adding the following line at the top of a file:
#include <registry.hpp>
Then pass the proper -I argument to the compiler to add the src directory to the include paths.
Unfortunately EnTT isn't documented yet and thus users cannot rely on in-code documentation.
Source code and names are self-documenting and I'm pretty sure that a glimpse to the API is enough for most of the users.
For all the others, below is a crash course that guides them through the project and tries to fill the gap.
EnTT has two main actors: the Registry and the View.
The former can be used to manage components, entities and collections of components and entities. The latter allows users to iterate over the underlying collections.
There are two options to instantiate your own registry:
By using the default one:
auto registry = entt::DefaultRegistry<Components...>{args...};
That is, you must provide the whole list of components to be registered with the default registry.
By using directly the Registry class:
auto registry = entt::Registry<std::uint16_t, Components...>{args...};
That is, you must provide the whole list of components to be registered with the registry and the desired type for the entities. Note that the default type is std::uint32_t, that is larger enough for almost all the games but also too big for the most of the games.
In both cases there are no requirements for the components but to be moveable, therefore POD types are just fine.
The Registry class offers a bunch of basic functionalities to query the internal structures. In almost all cases those methods can be used to query either the entity list or the component lists.
As an example, the member functions empty can be used to know if at least an entity exists and/or if at least one component of the given type has been assigned to an entity:
bool b = registry.empty();
// ...
bool b = registry.empty<MyComponent>();
Similarly, size can be used to know the number of entities alive and/or the number of components of a given type still assigned to entities. capacity follows the same pattern and returns the storage capacity for the given element.
TODO
TODO (ricorda di menzionare aggiunte/cancellazioni durante iterazioni)
TODO
To compile and run the tests, EnTT requires googletest.
cmake will download and compile the library before to compile anything else.
Then, to build the tests:
$ cd build$ cmake ..$ make$ make testTo build the benchmarks, use the following line instead:
$ cmake -DCMAKE_BUILD_TYPE=Release ..Benchmarks are compiled only in release mode currently.
If you want to contribute, please send patches as pull requests against the branch master.
Check the contributors list to see who has partecipated so far.
Code and documentation Copyright (c) 2017 Michele Caini.
Code released under the MIT license.
Developing and maintaining EnTT takes some time and lots of coffee. If you want to support this project, you can offer me an espresso. I'm from Italy, we're used to turning the best coffee ever in code.
Take a look at the donation button at the top of the page for more details or just click here.