3 ms·
The performance benefits comes from the "Systems", which is very infrequently talked about. Most uses of the term "ECS" are actually "Entity-Component" (EC), wh
by Jasper_ 6y ago
The performance benefits comes from the "Systems", which is very infrequently talked about. Most uses of the term "ECS" are actually "Entity-Component" (EC), which has been around for a long, long time.
The goal is to have "Systems" which operate on "Components", and "Entities" are completely out of the picture. The idea behind Systems is that they operate on a continuous block of memory:
for (auto &damagable : damagables) {
damagable.hp -= damagable.damage_this_frame;
damagable.damage_this_frame = 0;
if (damagable.hp <= 0)
damagable.dead = true;
}
for (auto &movable : movables) {
movable.position += movable.velocity_this_frame;
movable.velocity_this_frame = vec3(0);
}
Simple toy example, but by splitting up the data based on what acts on them, we have two loops that are very cache-friendly. Each of those two loops is called a "System".
The System is the key part of ECS that makes this work. Just splitting off components and still using a virtual update function isn't going to get you any performance benefits, but it's still most of what I see when I see "ECS" talked about online. In fact, making components contiguous while leaving your updates to be whole-entity-at-a-time is going to make your cache coherency worse!
Entities, then, are actually not "container objects", but often just uint32's -- all of their data is inside the Components. The database analogy: The Entity is just a primary key tying together a database of tables (Components). The tables can be acted on, sometimes in parallel, by Systems (UPDATE queries), regardless of the originating Entity.
Actual Systems in practice have dependency chains and other things, to make sure that updates are done in the right order, scheduling mechanisms, and ways to make cross-component talking safe, and performant.
Unity's GameObject is not ECS, despite it being an "Entity-Component" model. Their new DOTS stack is, but it has tradeoffs for that performance.
Put simply, "EC" is a way of structuring your data classes to not rely on inheritance, "ECS" is a way of structuring your algorithms that act on those data classes to not require virtual methods.
The rest of this thread has similar misconceptions, and even the original post makes some errors too. Sadly, this misinformation is widespread, and it's not really correctable at this point. Oh well.
- Pulcinella 6y agoYeah there is definitely some mental namespace pollution between EC and ECS where, as you described, you have “EC systems” (Entity-Component systems) and “ECS systems” (uhh “Entity-Component-System systems”). Actual Systems in practice have dependency chains and other things, to make sure that updates are done in the right order, scheduling mechanisms, and ways to make cross-component talking safe, and performant. Do you know if there is a formal term for this kind of dependency chain and update order scheduling is called? I’m interested in ways this kind of checking can be done at compile time, or at least a run time guarantee that things won’t be done in the wrong order and fails to compile/generates run time errors when you have a cyclic dependency rather than having to map that all out by hand.
- Twisol 6y ago> Do you know if there is a formal term for this kind of dependency chain and update order scheduling is called? ECS might make this an independent-enough concern that techniques from build systems would be applicable. See "Build systems a la carte" [0], for instance, which captures the (an?) essence of build systems as managing a graph of dependent dataflow processes. (In ECS, the dataflow would be mediated by the database of component tables, just as in Make the dataflow is mediated by the filesystem.) [0] https://www.microsoft.com/en-us/research/publication/build-systems-la-carte/ https://www.microsoft.com/en-us/research/publication/build-s...
- cma 6y agoTo go along with the parallel thing, you can imagine both of those loops are much easier to vectorize too compared to if each a was acting on objects with the damage stuff and position stuff combined in one structure.
- HelloNurse 6y agoEntities aren't out of the picture: those "damagable.damage_this_frame" and "movable.velocity_this_frame" attributes need to be assigned in a previous step, with lookups from component to entity and from entity to component. For example, a collision detection and handling step could iterate over all physical objects and, in case they collide, assign damage to the damageable component of the same entity and/or alter velocity of the movable component of the same entity (if appropriate).