Also: just having stuff in an array or vector invites you to the ABA problem. You need a generation counter in there too, or else the array indice may get reused if something is deleted and another thing is reinserted at the same index. But that's yet another boilerplate that would easily be overlooked if you had to do everything manually.
Also: you seem to be saying this with C++ in mind. Do you think that applies to bevy_ecs too?
Modern Bevy has relationships to make sure that if an entity has a component that refers to another, it doesn't become dangling. It works a bit like foreign keys in databases. I think this makes ecs much more usable
(as an aside, there is a whole host of analogies between ecs and relational databases. entity archetypes are tables, entities are rows, components are columns, and systems are queries). Nobody tells people to just write their database from scratch though)
It's really sounding like you're pretending not to know what your program does, which is one of the core OOP ideas that DOD refutes. In OOP you have an array of Shape and you pretend not to know which shapes your program implements, so the only way to draw them is to call ->draw() on each one. And you pretend you don't know anything about the lifetime of a shape so you use smart pointers everywhere to extend it as long as needed. In DOD you assert that you do know what shapes are available and what their lifetimes are.
Can you describe a superior replacement for generation counters?
Sounds like you're writing a game engine, not a game?
A generation counter offers a good deal in many common cases: for the fixed small cost of incrementing the generation counter when an entity ID is assigned a trivial test, also fixed cost, can disambiguate successively recycled entities that share the same number and tell which one is current.
This adds up to work proportional to the number of distinct entities plus, assuming obsolete references are eliminated, work proportional to the number of references to entities, which is clearly very good. Do you recommend a different way to solve the same problem? There is at least one obvious one.
Isn't most programming? Isn't struct Particle {vec3 position, velocity;} also the mother of all boilerplates?
Ooh here is a controversial one. DOD is premature optimization. Most programs don’t have enough data where the storage and access is a factor for performance. In fact it might be slower to use DOD.
One of the ideas in OOP that DOD is explicitly refuting is pretending not to know what your program does. You know which subtypes exist in your program and you shouldn't treat them generically as supertype instances except when that is actually optimal. On this axis, both ECS ideology and OOP ideology are opposite to DOD ideology. ECS happens to align with DOD in that it prefers big linear arrays, but it does not align in pretending not to know what combinations of arrays are used, which is similar to pretending not to know what subtypes of Shape exist.
Different paradigms come with different pathological cases. I've had to deal with Scala programmers whose notion of FP is making everything generic on the Monad it abstracts over, even when it'll only ever be instantiated on the one effect system the team uses. Nonsensical levels of generality is one of the classic OOP pathologies, and is the reason why we have aberrations like the AbstractSingletonProxyFactoryBean[0].
0. https://docs.spring.io/spring-framework/docs/current/javadoc...
I think it has nothing to do with OOP which I find very convenient for some domains and not so much or even opposite for others. These "Nonsensical levels" of anything is a disease which is called Architecture Astronauts Syndrome and victims apply it to any paradigm
Why? Flecs, for example, is pretty sick imo.
The first principles examination is you need an array of structs.
If your goal is to ship a product you would use this proven technique. It’s shipped more AAA and small games than any other.
The ECS is a hobby project which solves problems unrelated to your goal. (Making a cool ECS) And because it was not engineered with the goal of shipping you’re sitting on a pile of unknowns when you try to.
I find value in its reflection and serialization system, as well as it's pipeline API.
Games require far more than a bunch of arrays. The simulation code itself is dwarfed by the UI, VFX, animation and scene layout code. The APIs in Flecs have a lot of value for these "not the core game" use cases.
Conversely, the amount of boilerplate you have to write to stand something up in Flecs is massive. And the use of macros in Flecs APIs tends to break editor auto complete. And the learning curve is very big. And the output code just looks very different from Orthodox C.
Getting nerd trapped fucking around with ECS is a real risk. The rabbit hole goes deep. But the library itself is valuable, powerful and well done.
This is my honest thoughts on ECS systems derived from first hand experience.