[HN Gopher] Component Graph System (2017)
       ___________________________________________________________________
        
       Component Graph System (2017)
        
       Author : Kinrany
       Score  : 78 points
       Date   : 2021-07-16 12:52 UTC (10 hours ago)
        
 (HTM) web link (github.com)
 (TXT) w3m dump (github.com)
        
       | syntaxfree wrote:
       | I don't know what ECS is. You should define the acronym...
        
         | anentropic wrote:
         | Entity Component System
         | 
         | commonly used in game programming
        
         | mrspeaker wrote:
         | "Entity Component Systems" are common in game engine
         | architecture, and there are a lot of variations on them - but
         | they are a high-level architecture for making modular behavior
         | in games. Generally they were thought of as "better than Object
         | Oriented, because they very very heavily favor composition over
         | inheritance."
         | 
         | The idea is that everything in your game - like Players, NPCs,
         | Bullets - are _Entities_. Entities are simply an ID. That 's
         | their only property. Nothing else.
         | 
         | But there are _Components_ - they have the data. For example,
         | you might have a `PositionComponent` that has an `X Position`
         | and `Y position` property. And maybe a `MassComponent` that has
         | a property `Mass`. Somewhere in the framework (like a database
         | table), a given Component will be related to a given Entity ID.
         | The Entity therefore becomes a  "bag of Components" through the
         | relations.
         | 
         | Finally there are _Systems_. They do stuff with the data. One
         | system might be `GravitySystem`. It doesn 't care directly
         | about `Entity`s, but can query the relations. It might ask for
         | anything that has BOTH a `PositionComponent` and a
         | `MassComponent` (it doesn't know which Entity it is for - it
         | only gets the Components). It takes any `PositionComponent`s it
         | gets and applies gravity: `component.y += gravity`.
         | 
         | The effect is that you can mix and match Components in weird
         | and wonderful ways without having to hard-code behavior and
         | rules for certain entities. You can obviously achieve this with
         | other architectures too - but that's the primary goal of this
         | one.
        
           | thom wrote:
           | Correct me if I'm wrong, but isn't one of the other
           | motivations to store your data in CPU/memory management
           | friendly ways? It's not purely about developer ergonomics.
        
             | mrspeaker wrote:
             | I think originally it was primarily about developer
             | ergonomics - here's the first thing I ever read about them
             | in 2007 where they tested it on Tony Hawk Pro Skater
             | (http://cowboyprogramming.com/2007/01/05/evolve-your-
             | heirachy...). The CPU/memory management has been an on-
             | going discussion ever since! Being able to process domains
             | as flat arrays helps with cache misses - but there is a lot
             | of other overhead, depending on how you designed
             | everything.
             | 
             | Making it performant was one of the big problems initially,
             | and it seems like the `Component Graph System` this thread
             | is about trying to answer "how do systems efficiently
             | process components?"... But I don't really get how it
             | answers that actually.
        
               | jmiskovic wrote:
               | My reading of CGS is that it also means to boost
               | ergonomics. Without "entity" concept of ECS triad, it
               | should be 33% easier to understand how everything works,
               | and what pitfalls exist.
        
               | gmueckl wrote:
               | As far as I understand it this is about the ECS
               | equivalent of an INNER JOIN, that is, some variation on
               | "iterate over all entities that possess instances of
               | component A and B". Iterating over single component types
               | in a system is trivial if they are separated into pools
               | by types. When you have a system requiring more than one
               | component, it isn't that easy to do better than iterating
               | over all entities and checking whether they possess each
               | required component. You can decide to maintain back
               | references from components to their entities, but this
               | means that you incur that management overhead pretty much
               | globally. This essay says that doing away with entities
               | altogether and just keeping direct links between your
               | components is better. And it probably is when it comes to
               | handling related components.
               | 
               | However, I believe (without having actually tried it)
               | that this proposal has its own drawbacks. it's harder to
               | thoroughly clean up all components that form a single
               | entity. My suspicion is that it's easier to produce bugs
               | like keeping e.g. a stray collision shape or sound source
               | around while the other parts of an entity are removed.
               | All you need for that to happen is an incomplete graph
               | traversal.
        
               | Kinrany wrote:
               | I think CGS boils down to smart links between components,
               | which may include SQL-like automatic checks: deleting
               | components that refer to deleted components or components
               | owned by the deleted component.
        
             | m12k wrote:
             | Correct, you basically invert the typical component/object
             | oriented approach, so each property relating to some
             | Component isn't stored in memory alongside the game object
             | it relates to (causing the values relating to e.g. physics
             | to be scattered around memory) but is instead stored in an
             | array (indexed by an id - the Entity id) with all the other
             | values for this component type, making it much more cache
             | efficient when a System (e.g. particle system, physics
             | system) needs to perform updates on all components of a
             | given type (which typically happens once per run loop
             | iteration in a game engine). See also
             | https://en.wikipedia.org/wiki/AoS_and_SoA
        
         | jcelerier wrote:
         | there are two distinct definitions of ECS, the first one given
         | in https://news.ycombinator.com/item?id=27856030 is the
         | "(entity-component-system) architecture" where there are
         | entities, components, and systems, as distinct objects in your
         | software. The second is "(entity-component) system" or "entity-
         | component architecture" where the behaviour goes inside
         | components (for instance, Unity3D gameobjects with their
         | components).
        
         | nodejs_rulez_1 wrote:
         | It's good old procedural programming. Systems (procedures) are
         | mutating state (components) grouped by a common ID (entity).
        
           | leoc wrote:
           | I'm no expert on any of this but that doesn't seem right; is
           | it? IIUC, most procedural programming is nearly as wedded to
           | the "one entity, one master data structure, one address in
           | memory" frame of mind as OO is. (And the same is true of most
           | functional programming, come to that.)
        
           | bordercases wrote:
           | You could do it functionally, i.e. the systems are all
           | reducers on partial states of the world.
        
       | m0llusk wrote:
       | > CGS is more flexible thus targeting a wider use case than
       | generic ECS: it's a hierarchy of components instead of the flat
       | entity-component duality ...
       | 
       | Wasn't the flatness of ECS supposed to be a useful feature that
       | simplifies things like iteration and searches?
        
       | gameman144 wrote:
       | > And we decided that each system processes relevant entity data
       | by iterating through entities first. Now we have another problem
       | - growing the number of entities slows down every system, even
       | the ones that are not related...
       | 
       | Call me out if I'm wrong, but I don't know of any high-
       | performance ECS framework that actually does this. Most
       | frameworks maintain sorted collections of components with no
       | gaps. For instance, if I want all entries with X,Y,Z, then I
       | iterate those three arrays starting at their X,Y, Z section, and
       | the order of components in that section of the arrays matches
       | exactly (meaning we can just iterate through them all).
       | 
       | This library seems like a really neat concept, but I think the
       | ECS concepts that it's critiquing aren't actually used in many
       | production-quality frameworks. Call me out if I'm just missing
       | context here.
       | 
       | Also, I'd love more details on how CGS is able to always iterate
       | on flat vectors with no gaps. The only way I've seen to
       | accomplish this is to do a decent amount of work curating
       | components into multiple orderings, so if CGS is avoiding that, I
       | am equal parts skeptical and _very very excited_ (since that
       | would be super useful!)
        
         | jayd16 wrote:
         | Agree. This presents a bit of a strawman of ECS. No reason
         | components can't reference others or Systems can keep look up
         | tables in ECS.
        
         | hrh wrote:
         | What libraries/frameworks are state of the art?
        
           | xaedes wrote:
           | There is EnTT, an ECS as C++ library:
           | 
           | EnTT is a header-only, tiny and easy to use library for game
           | programming and much more written in modern C++. Among
           | others, it's used in Minecraft by Mojang, ...
           | 
           | https://github.com/skypjack/entt
        
             | gameman144 wrote:
             | EnTT is the one I was thinking of -- I'd _highly_ recommend
             | looking into its implementation, as it 's both very well-
             | documented and readable, and blazing fast.
             | 
             | The fact that even this caliber of implementation has to
             | handle multi-component cases by doing _super_ careful
             | curation of components is what makes me skeptical that CGS
             | would be able to solve this situation more efficiently
             | /easily. I would be _very_ happy to be proven wrong here,
             | though.
        
           | jayd16 wrote:
           | Unity's implementation is well documented and handles this.
        
       | [deleted]
        
       | enbugger wrote:
       | >Performance-wise, some overhead may come from reference-counting
       | the components
       | 
       | Well, that's what ECS gets rid of and mainly benefits from that.
       | Doesn't returning it back mean going back to OOP? What's the
       | point then?
        
         | Kinrany wrote:
         | I believe the main benefit is a constrained form of dynamic
         | typing.
         | 
         | You don't want to lose compile-time type checking and
         | intellisense, and you want to keep most of the performance
         | benefits. But you want to be able to add data types without
         | recompiling.
        
       | Kinrany wrote:
       | > There is no ~~spoon~~ entity. What was our entity like? A
       | structure with pointers (IDs) to different components. Now, let's
       | treat it as just another component! The whole ECS becomes
       | simpler.
       | 
       | To me this is the most interesting part. Game logic needs
       | components with references to other entities and components
       | anyway. And if there's _some_ way of identifying components, you
       | no longer need entities to have identities.
       | 
       | And you can still apply all the optimizations as long as you
       | treat some components as "entity" components. But only when you
       | want to exchange simplicity for performance.
        
       ___________________________________________________________________
       (page generated 2021-07-16 23:02 UTC)