A Critique of the Entity Component Model

Published April 03, 2014 by Sean "rioki" Farrell, posted by rioki
Do you see issues with this article? Let us know.
Advertisement
The entity component model is all the rave for the last decade. But if you look at the design it opens more issues than it solves. Broadly speaking the entity component model can be summarized as the following: An entity is composed of components who each serve a unique purpose. The entity does not contain any logic of its own but is empowered by said components. ecm-intro.png But what does the entity component model try to solve? Each and every illustration of the entity component model starts with a classic object oriented conundrum: a deep inheritance hierarchy with orthogonal proposes. For example you have a Goblin class. You form two specialisations of the Goblin class, the FylingGoblin who can fly and the MagicGoblin who uses magic spells. The problem is that it is hard to create the FylingMagicGoblin. dreaded-diamond.png Even with C++ and its multiple inheritance, you are not in the clear as you still have the dreaded diamond and virtual inheritance to solve. But most languages simply do not support a concise way to implement it. When solving the issue with components, the components GroundMovement, FlyingMovment, MeleeAttack and MagicAttack are created and the different types of goblins are composed from these. flying-magic-goblin.png Good job, now we went from one anti-pattern (deep inheritance hierarchy) to a different anti-pattern (wide inheritance hierarchy). The central issue is that the inheritance hierarchy tries to incorporate orthogonal concepts and that is never a good idea. Why not have two object hierarchies, one for attack modes and one for movement modes? goblin-sanity.png As you can see from an object oriented standpoint the entity component model fares quite poorly. But that is not the only problem the entity component model tries to solve. In many cases you see the concept of a data driven engine. The idea is that you can cut down on development time by moving the object composition out of the code and into some form of data. This allows game designers to "build" new objects by writing some XML or using a fancy editor. Although the underlying motivation is valid, it does not need to use an entity component model, as a few counter examples show quite well. Putting the structural criticism aside, a naive implementation of the entity component model can in no way be efficient. In most cases the components are not such high concepts as moving or attacking, they are more along the lines of rendering and collision detection. But unless you have additional management structures, you need to look at each and every entity and check if it has components that are relevant for the rendering process. inefficient.png The simplest way to resolve the issue, without altering the design too radically, is the introduction of systems. In this case the actual implementation is within the systems and the components are just indicating the desired behaviour. The result is that a system has all the relevant data in a very concise and compact format and as a result can operate quite efficiently. better-graphics.png But if you look closely you can see that we have all these useless components. What if you removed the components and just used properties on the components and the systems just look for appropriately named properties? Now you have duck typing. duck-typing.png Duck typing is a concept that is used a lot in weakly typed languages, like for example JavaScript or Python. The main idea here is that the actual type is irrelevant, but specific properties and function are expected on a given object within a specific context. For example it is irrelevant if it is a file stream, a memory stream or a network socket - if it has the write function it can be used to serialize objects to. The problem with duck typing is that is does not lend itself easily to native languages. You can cook up some solution using some varying type but in no way is this an elegant solution. Chances are you already have a scripting system, in this case the solution is quite straight forward, you implement the core game logic in scripts and underlying systems look at this definition and implement any heavy lifting in native code. The idea of alternating hard and soft layers is nothing new and should be considered where flexibility and performance is needed. You may think that implementing the game logic in scripts is an inefficient way to do it. In cases where you are building a simulation-oriented game this may be quite true. In these cases is makes sense to extract your logic and reduce it to its core concepts, a simulaiton if you will. Then implement the presentation layer and control layers externally directly against the simulation layer. totally-not-mvc.png The nice thing about this design is that you can split the presentation layer and simulation so far that you can put one of them on one computer and the other on a different one. mvc-network.png Wait, did you just describe MVC? Um... No... Stop changing the subject. When looking into scalability you get interesting requirements. One very clever implementation of the entity component system was make it scale in an MMO setting. The idea here is that entities and components do not exist in code, but are entries in a database. The systems are distributed over multiple computers and each work at their own pace and read and write to the dabase as required. mmo-ecm.png This design addresses the need of a distributed system and reminds me of the High Level Architecture][10] used by NASA and NATO to hook up multiple real-time simulations together. Yes this design approach even has its own standard, the IEEE 1516. Ok, oh wise one, what should we do? If you read about these issues you are either building a game engine or a game. Each and every game has different requirements and game engines try to satisfy a subset of these different requirements. Remember what you are developing and the scope of your requirements. If your current design sucks, you do not need to go overboard with your design, because chances are you aren't gonna need it. Try to make the smallest step that will solve the problem you are facing. It pays out to be creative and look at what others have done.
Cancel Save
0 Likes 35 Comments

Comments

DanielKrej?

Interesting article. I am working with entity component model lately and so far I am more satisfied with it than with OO. It needs a lot of mental adjustments to understand how to design the game differently.

Anyway, I want to point out one thing. When you remove components from the flow and store all data in the entities, you are losing some important features - shared and/or reusable data.

Components as the smallest data unit can be easily shared among other entities. That means you save some memory and also some processing time, because changing component in one entity makes that change applied to all other entities that contain this component. That can be very useful in some scenarios.

For example you want your weapons to have all the same base stats. You can create one component with that and assign the reference to all weapons created. Later you may decide that all these weapons need little tweak on one stat, so you just change it in that one component and it's all good. If you need one weapon to be special and stand out, you give it just its own component with own stats.

Other feature I have mentioned is reusable data. This can be handy for example for positioning. Instead of having like 10 components with the same X,Y,Z just because there is more items on that very spot, you can simply share one component among them. Other use is for pooling where entity gets removed, but some frequently used components can be stored in stack and reused for new entity. Garbage collector will be more happy this way, less mess to clean up and smaller overhead in creating those objects all over again.

April 01, 2014 10:26 AM
BrokenKingpin

FredyC, maybe I am reading your post wrong, but your entities should not share the same instance of your components. If the property of component changes at run-time, it it would change for all the entities that have a reference to it, would probably would not be desired in most games.

For the example you gave where you want to change the stats of an item, that would just be changing the stat in code or config, and anyone who creates an instance of that item would have the new stat. Unless you want to change that stat at runtime, but again this would not be the way to handle that.

----

For the me the component entity model makes things easier because you have systems that manage the relationships between entities, and the world. The components themselves are just a set of properties, and all the logic an interactions are managed in the systems. When all the logic is contained in the entities themselves, then it gets tricky as they need references to the map and the rest of the world to handle all the interactions.

April 01, 2014 01:21 PM
DanielKrej?

I think you are reading it correctly, although I didn't meant to share all the components. It's per case and if it desired by design. I just wanted to point out, that by removing components completely, you are losing this possibility, because each entity needs to have own copy of data.

April 01, 2014 01:28 PM
DevilWithin

The article is well-written but in my opinion is kind of vague and speculative..

Both OOP and ES approaches can solve _most_ games in arguably the most efficient way.. I guess they are both perfectly valid in many aspects. But there is a reason people are tending to change into ES progressively. It compromises speed in some cases but is always a more powerful and flexible solution if done right. I've even seen implementations where ES performs better!

As the OP said, choose the tool right for the task. In most cases, either of the approaches will probably do. But you can hardly get it wrong with a good ES, imo.

April 01, 2014 02:09 PM
Kylotan

Hmm, I agree with the first paragraph of the article, but not much of the rest!

Firstly, there's no requirement to create a bunch of hierarchies, one per component type (eg. movement, attack). There's no real reason why you need a different interface in each of those cases. There are situations where you think you might benefit from one - eg. compile-time binding of intra-component dependencies - but it's not mandatory. And if you move away from rigid type systems like C++ or Java, you don't need it at all. It's 2014; you don't have to treat scripting languages as a magic wand you wave at the end of an article.

Secondly, the whole systems/duck typing thing makes no sense. If you know you need to query for a renderMesh, you could look that up by name, or by type, or by registering it with an observer pattern, etc. There are many ways to join that up without requiring that the GraphicsSystem looks it up strictly by the property name. And really you've not removed useless components; the renderMesh is the component. You just have the processing logic elsewhere. And that's how a lot of people like to make these systems. Ultimately, having a rendering system inspect your data to find a renderMesh is equivalent, both in terms of the toolchain used and the results produced, as adding in a component derived from a Renderable interface. You swap out those objects to change the behaviour.

Thirdly, you cite a 'very clever' implementation of the entity component system, that was vaunted to be superior for MMOs. The series of articles you cite, though strangely popular, is also strangely vague on implementation, seriously mischaracterises object-oriented programming, does not make a solid case for why it is better, and in fact I'd be surprised if anybody is using it in a production setting. Most MMOs do not want to be reading and writing to a database that often. It's true that many MMOs will split processing tasks across multiple servers, but generally it's both necessary and desirable to have a central process that mediates everything rather than trying to enforce an entity's segregation in impractical ways. 90% of the problems people encounter with components are trying to get them to work together adequately, and handling different components on different servers just ratchets up the pain there by a large margin.

I agree that component-based systems have become a strange fad that ask more questions than they answer. But I think you're criticising the wrong aspects, and not really suggesting a concrete solution.

April 01, 2014 02:26 PM
LoneDwarf

Nice to see an article taking the other side the Entity Component System (ECS). I have been meaning to make a post asking people how they feel about the ECS now since Scott Bilas started talking about it way back when. I bought into the concept and armed with my hammer started to look for nails, if you get my meaning...

Eventually the Kool-Aid wasn't what I thought and I trashed the ECS and went back to more traditional methods and just got things done again. So much time was spent trying to make the ECS work and very little time getting game features done.

Composition can be used within a Entity without going with a full blown ECS. An Entity that 'has a' model works fine. Make the model an interface if you need to. Is making the everything engine for the everything game your target? Are writting you middleware? If not then just move on and get things done.

The sharing data/properties isn't really part of the scope for this article or ECS really. An Entity can have a master prototype that defines all the const data for it. One method can have these values copied to the instance when created (fire and forget). Another method might hold a delta from it's prototype (think of lua tables going to it's index meta method when a value isn't found).

I'm not saying that ECS are wrong or bad as I have never shipped a game with one. I just tend to wonder. Also is it just me or does the pitch for an ECS sound like the pitch that RAD tools used to use? "Look how fast you can make a calculator!" Amazed you go home only to realize, ah, I'm not making a calculator...

April 01, 2014 02:41 PM
mmakrzem

I think you have some typos. The Flying Goblin class is named FylingGoblin instead of FlyingGoblin.

Melee is spelt with three 'e'

April 01, 2014 03:36 PM
Wrathnut

I am also glad to see an article that is questioning entity component systems. I am curious why people say it is entity-component vs OOP since and entity component system is a design pattern that uses OOP.

I am not 100% certain about all of the critiques but my take away from the article is don't waste your time trying to build a system like everyone else uses. Build a system that gets the job done. Whether it is 'OOP' or ECS, build what you need to finish your game.

April 01, 2014 04:46 PM
jpetrie

While I'd be the first to agree that a lot of people use (or overuse) component-based implementations of entity systems, I don't think this article does a very good job *at all* of addressing any of the actual subtleties of the problems inherent in them. Everything is painted in extremely broad strokes, often choosing rather poor fundamental examples of component-oriented (or more generally aggregation-over-inheritance) designs, making assumptions that those are the only ways to implement such a system, and then making logical leaps to very complex implementations to illustrate how "bad" this is.

April 01, 2014 05:00 PM
Bleys

There is a library that gives you such duck typing in C++ allowing you to have a middle ground decision if you don't want to sacrifice the performance when you use a scripting language.

The library is made for the Boost collection, but it's not a part of it yet. It's pending review.

Docs link: http://ibob.github.io/boost.mixin/
Source link: https://github.com/iboB/boost.mixin

April 01, 2014 05:01 PM
jpetrie

I think you have some typos. The Flying Goblin class is named FylingGoblin instead of FlyingGoblin.

Melee is spelt with three 'e'

Yeah. Also "allot" isn't a word that means "many."

I also think that "funny" commentary like the "did you just describe MVC" and the "oh wise one" quips detract from the otherwise serious nature of the article.

April 01, 2014 05:05 PM
phil_t

Having used an entity component system in a few medium-sized projects, I have some opinions here.

First of all, you make some statements I do agree with: An ECS isn't necessary to solve the "dreaded diamond pattern", and it also certainly isn't necessary in order to be able to instantiate objects based on a description in a text file (although it probably makes it easier).

The rest of your article kind of wanders away from ECS criticism though (indeed, the second half doesn't really seem to have much to do with ECS). And the few criticisms you make, I don't agree with or don't understand.

Good job, now we went from one anti-pattern (deep inheritance hierarchy) to a different anti-pattern (wide inheritance hierarchy). The central issue is that the inheritance hierarchy tries to incorporate orthogonal concepts and that is never a good idea.

I'm not really sure what you see as the problem with a wide inheritance hierarchy. Yes, orthogonal concepts are grouped together under a single Entity. That's kind of the point though. Logic (in the systems) operates on individual components though, so I don't see the problem.

Putting the structural criticism aside, a naive implementation of the entity component model can in no way be efficient.

That's true for pretty much anything.

The simplest way to resolve the issue, without altering the design too radically, is the introduction of systems. In this case the actual implementation is within the systems and the components are just indicating the desired behaviour. The result is that a system has all the relevant data in a very concise and compact format and as a result can operate quite efficiently. But if you look closely you can see that we have all these useless components.

A minor point: technically, the introduction of systems doesn't necessarily allow or restrict where components can be stored. You could store them in compact per-type arrays even without systems, and even with systems you could store different component types right of the entity.

"We have all these useless components": I don't understand what you mean by this.

In my usage of an ECS, these are some problems I think are actually issues:

- Debuggability. It becomes more difficult to identify objects in the game world (e.g. is the the player character? I have no idea, all I'm looking at right now is a meshcomponent that is being interpreted by the graphics system). It's more difficult to put a breakpoint and step through the logic applied to a particular entity.

- "Communication between components". That's in quotes, because components don't really communicate between each other, given that logic tends to exist in the systems instead. So what I'm getting at is that while it is nice to think you have pieces of isolated code each each system, sometimes they do need information from each other. An example would be where one system is responsible for organizing entities into a data structure that allows for quick retrieval/search based on position, and other systems need to access this data. The important thing to remember though, is that ECS is not an alternative to other design patterns - it works with them. Use the right abstraction where you need it.

- Most systems operate over more than one component. Often, performance is a stated goal of ECS implementations: operating on one piece of code logic at a time on one type of data which is stored in a contiguous chunk of memory can help avoid cache misses. However, when a system needs process multiple components on an entity (e.g. Physics and Position, say), this theoretical performance benefit can be lost, since sequential access in one component array may mean random access the other component array.

Here are some areas where I think ECS shines:

It really encourages complete separation of concerns. Systems only look at the components they need - they just touch the data they're interested in. The result is that you end up with small pieces of independent logic that comprise your game. This makes it very easy to change parts of your code without risking breaking other parts.

An ECS creates friction against writing big monolithic spaghetti code or creating unnecessary dependencies, thus encouraging you to refactor/organize things in a better way.

It really discourages code duplication, since you are encouraged to create component/systems for any pieces of reusable logic - and thus that same logic is easily applied to any entity. Less code equals less bugs, period.

The bigger and more complex your game becomes, the more these benefits will become apparent. I find I can get more done with less code when using an ECS, as opposed to "traditional OOP", and I spend a lot less time fixing bugs.

April 01, 2014 05:42 PM
DanielKrej?

Here are some areas where I think ECS shines:

It really encourages complete separation of concerns. Systems only look at the components they need - they just touch the data they're interested in. The result is that you end up with small pieces of independent logic that comprise your game. This makes it very easy to change parts of your code without risking breaking other parts.

An ECS creates friction against writing big monolithic spaghetti code or creating unnecessary dependencies, thus encouraging you to refactor/organize things in a better way.

It really discourages code duplication, since you are encouraged to create component/systems for any pieces of reusable logic - and thus that same logic is easily applied to any entity. Less code equals less bugs, period.

The bigger and more complex your game becomes, the more these benefits will become apparent. I find I can get more done with less code when using an ECS, as opposed to "traditional OOP", and I spend a lot less time fixing bugs.

I think this is very nice summary. I just would like to add one more - testability. Writing unit tests for systems is much more easier as you can just set input value for the component and then write expectation for the value in the component. It cannot get easier than that.

And for the debuggability ... it is true that breakpoints for one entity are hard to achieve, however there is opportunity in the fact, that you can make "snapshot" of the entity and then rerun this snapshot through the systems how many times you want. Since everything is so separated, you could even run whole code with just that entity there and see what those systems are doing with it. Having unit tests (ideally with 100% coverage) really helps too as you can just apply this snapshot there and see where it breaks.

April 01, 2014 06:16 PM
Klutzershy

I agree, the canonical entity-component-system design has its flaws.

However, I think the article is missing the point a bit; it's attacking more the idea that design patterns are rigid and have to be adhered to. I think the greater picture of entity-component-systems is that composition works better for game objects than inheritance, not that everything needs to conform to a strict philosophy.

The best programmers use the tools they need, not the one tool they were recommended to use.

April 01, 2014 08:57 PM
Servant of the Lord
I "approved" the article because criticism is good, and promotes discussion, and the article is acceptably formatted and reasoned. I also disagree with it, because I think it's inaccurate and I think that the author hasn't yet really understood ECS systems enough to critique it knowledgeably (this is my personal opinion. For all I know, he could've invented ECS laugh.png).
A) One of the major complaints in the article was against wide-inheritance. Most ECS systems I've seen don't use inheritance, as inheritance defeats one of the major strengths of ECS systems: Composing entities at runtime (inheriting components would have to happen at compile time).
Even one of the articles that was linked to, 'Evolve your hierarchy' is advocating "aggregation over inheritance", and "objects as pure aggregation". i.e. NOT inheriting your components. wink.png
B) MeleeAttack, MagicAttack, FlyingMovement, and GroundMovement sound like pretty poor components. The article is applying a single ECS to both the entity's attributes and the logic of the entity simultaneously, which seems like it'd get very messy very quickly.
C) One of the suggestions in the article for ECS architecture is the addition of "systems". ECS stands for Entity Component Systems, and (often) have those kind of systems already.
ECS doesn't get rid of object-orientedness. Not only is ECS a form of OOP, it's a different architectural pattern that shouldn't be applied willy-nilly, but that does seem to be one of the best patterns we've discovered so far for game entity creation. We found other architectural patterns for other parts of games - for example, certain types of logic is still better described through scripts, state managers, and other patterns, and GUIs don't fit perfectly with ECS either.
A game, being a complex piece of software, should use multiple different paradigms and multiple different architectures for different portions of itself. But when you take one paradigm or one architectural pattern, and apply it as a law to every part of the code then the overall structure of your game gets overly convoluted.
Overall, I think the article is looking at ECS through the wrong lens - different architectural patterns must be looked at through the lens of their own paradigm, and one paradigm never gives the whole picture. When reading this article, I get the impression that the article doesn't fully comprehend ECS (because of the lens it is using), because it makes several statements and present several examples that are butchered ECS instead of critiquing good ECS practices.
By thinking of ECS as "Not OOP", for example, the article seem to think MVC and components are competitive or contradictory, or that components unnecessarily reinvent MVC. This isn't the case - ECS is fully compatible with MVC.
ECS is the flavor-of-the-month so alot of people are overly enthusiastic about it and advocate it maybe a bit too strongly, perhaps without understanding what it's benefits are. But beneath the hype, ECS could really fit the needs of complex games.
That said, the more critique it gets, the better it can be refined. Bear in mind that OOP and MVC (neither of which are incompatible with ECS) has been refined over almost 40 years now. ECS is still in its infancy, having stuck its head out around the year 2001, and went more "maintstream" among programmers only a half-dozen years ago.
April 02, 2014 04:08 AM
TheChubu

But if you look closely you can see that we have all these useless components.
Why? Why they're useless?You seem to imply it is obvious they have become useless somehow, yet all I see is a pretty clear distinction between behavior (systems) and data (components). Normally you'd stop there, with your components attached to entities and the systems with sets of the different component types they need to work on.

You state no good reason to remove components at all after that point, thus no reason to follow with your argument further (that quickly gets derailed but that's a different issue).

Right until that point I was following you perfectly, but then you state out of nowhere that the components are useless then proceed to butcher up what you had built for no reason.

April 02, 2014 05:24 AM
rioki

I am honestly humbled by your constructive criticism. I must admit that writing this article was sort of a knee jerk reaction to yet an other starry eyed ECS article. After some introspection, I think my biggest qualm is not the ECS itself (it is just a pattern after all), but the naive and oversimplified rhetoric surrounding the issue. It is a bit like the screen graph gospel two decades ago. (Two decades?! I feel old.)

This article went through half a dozen revisions and rewrites, ranging in tone between CS paper and the ramblings of a crazy old man. I settled for my normal and rather informal writing style, I picked up from Jeff Atwood. The tone shifts at the end are sort of intentional, they interrupt the lull of the rhetoric and as a result make you question your line though and my reasoning. I must agree that this stylistic element is not the most popular.

Typos... I am dyslexic and even though I put a lot of effort into checking my writing for spelling mistakes, some always end up in the text. I am grateful for each typo found; i would rather have somebody point it out, than having the mistake linger.

Although I could have spelled it out more explicitly, the "OOP vs ECS" discussion is a non-starter and misses the point. Each and every article I have ever read about the ECS hat two problems it tried to address, a deep inheritance hierarchy and a god class. The problem is that the ECS is not the solution to these problems, it is rigorously refactoring the biggest offenders of well established OOP design principles. The result will probably not resemble even closely an ECS.

But if the ECS does not actually address deep hierarchies or a good class, what does it solve? It provides flexibility where none would be. I fully agree with the approach the Unity engine took. Their use of the ECS is the solution to the problem "How do we get game designers to build objects without code?".

It is no coincidence that the other place I found an ECS outside of game development was in the implementation of a scripting engine. The ECS is great at providing a high level of flexibility, especially for run-time composition and for this it does the job quite well.

The flip side of the argument is that, if you need this high level of flexibility, why are you using a strongly typed language anyway? So my question is, if you need this high level of flexibility why are you actually not using a weakly typed system? It is shocking how few developers even know about the concept of duck typing or soft/hard layer mixing.

The reason why I did not delve into the specifics, such for example debugging, is because the ECS is already mildly flawed on a design level. What is bad about a wide inheritance hierarchy? The term you are looking for is "ravioli code".

One of the my biggest issues I have the articles about ECS is that few talk about how an ECS could fit into the entire engine. There are sane ways to integrate a ECS into your game, but none of the code samples I have ever seen get close sanity. (If you have actual rendering code in your components, you are doing it wrong.)

There are valid uses cases of a ECS, where the benefits outweigh the flaws. The important part is to be aware of these flaws and keep and open mind. Maybe the problem you are trying to solve can be solved differently than you initially though.

Thank you for the feedback, my writing and reasoning is far from perfect.

April 02, 2014 09:22 AM
lrh9

Any design or methodology can be misapplied. It can be easy to criticize those misuses, especially when they are common. They should be, but good ideas should not be discarded because of bad practices.

In my idea of a good ECS there are no hierarchies. Do note that in your proposal to have separate hierarchies you don't avoid the issue you are concerned about. Instead you just move it to a different level of the hierarchy. A designer could want a goblin that can both fly and walk, or one that can both use a sword and cast spells.

To me, ECS is the end result of the thorough application of duck typing. Rather than thinking of entities in terms of Goblins and Attacks, and Melee and Magic, ECS requires the designer to think in terms of what they want their entities to consist of (components/data) and what operations can be applied to them (systems). In this way of thinking (properly applied) it no longer matters what the entity is, but what can be done with it.

Personally, I do favor the use of ECS for core/engine code and eschew it for entity logic. The engine is where ECS can be most easily applied. For example, you can have an entity with a position component and a velocity component and your physics system can do integration (Euler, RK4, etc.) to update that entity's components. A.I. isn't always so simple. In that case I favor scripts, which can easily be integrated in the ECS by having entities have a scripts component and a system that calls relevant script hooks during each logic update.

April 02, 2014 11:08 AM
DejaimeNeto

you need to look at each and every entity and check if it has components that are relevant

It looks like you are not criticizing the ECS, but an awful variation of it; IMHO, your article would be better off titled "A Critique of Badly Implemented Patterns". The problems you listed for ECS are basically bad implementation, while the real problems aren't even mentioned.

Usually, what annoys me when using ECS is that it ramps up the complexity of my systems, when compared to a simple class hierarchy. It creates the necessity for more code and new patterns to be inserted in the model, such as observer and factory, when they would be unnecessary otherwise. This increased complexity weights a lot when debugging, specially when we have component-component communication.

Of course, it does have its fair share of problems, but it usually doesn't open more issues than it solves. I'd say it changes the issues, one solution for one problem. But in many many cases it is worth it.

And I can't really see what problem you are trying to solve with Duck Typing...
April 02, 2014 02:06 PM
assainator

From reading the replies, I conclude there are (a lot of) of downsides to ECS that haven't been covered in this article. Would someone be willing to write an article that tackles (some) of these downsides?

April 02, 2014 02:20 PM
Servant of the Lord

Semi-informal writing styles work excellently for a blog post, but less so for article formats, IMO.

The grammar, spelling, and structure of the article is fine. There were hardly any typos or misspellings - not any more than other articles. smile.png

I'd love to read more articles written by you.

April 02, 2014 08:38 PM
SuperG

I am also glad to see an article that is questioning entity component systems. I am curious why people say it is entity-component vs OOP since and entity component system is a design pattern that uses OOP.

I am not 100% certain about all of the critiques but my take away from the article is don't waste your time trying to build a system like everyone else uses. Build a system that gets the job done. Whether it is 'OOP' or ECS, build what you need to finish your game.

Yes I think its component and aggregation vs inheritance pattern. I think a game might need both solution where the one or the other make most sense. And it's more Data oriented design vs OOP.

The way I see the benefit is compute your stuff more from the perspective of the hardware architecture of how CPU or GPU interworking with caches and memory. Like memory alignment and keep data sets within cache lines. vs OOP real-world moddeling of how humans see it.

It's like this singleton types of component manager process after each other where each goes through a large set of its component objects but split over as many cores so many threads as possible.

The world is shifting to many cores CPU the high-end will go to 8 cores HT so eats 16 threads. And it doesn't stop there.

These data oriented and component driven solution support concurrency in much better way.

That what I make out of all those articles in books and on the internet.

For a novice like me those articles make sense. This not so. It doesn't convince me at all.

April 02, 2014 09:24 PM
rioki
These data oriented and component driven solution support concurrency in much better way.

Yes! No! Maybe! Having implemented many a system, inside and outside of game development, I can say that a ECS does neither favor nor deter from a solid concurrent execution model. The most solid case for the ECS is the Intel Paper Designing the Framework of a Parallel Game Engine. Even through they never lose either the words entity or component, if you look at their universal object and associated specific system objects, it quickly looks like an ECS. In this paper they basically do functional decomposition to use as much concurrency as possible.

On the other hand in their excellent video series Don't Dread Threads, they make the very valid point that function decomposition has it's limits. You may actually get more out of your system by doing data decomposition. The key benefits here are two, first you probably can provide a higher level of concurrency and in most cases you can get away with almost no synchronization primitives. Using openMP to parallelize a few core loops may actually give your the biggest bang for your buck. Granted the real art is to do both, functional decomposition and data decomposition.

The thing that an ECS provides is an extreme level of flexibility at the cost of added complexity. In regard to concurrency it fares similar to other solutions. The key point here is added complexity; if a small simple system outperforms on one core because of memory locality an ECS with a high level or concurrency, you have gained nothing. Only use and ECS if you really need these extreme levels of flexibility.

Concurrency is like with optimization, don't do it until you really need it.

April 03, 2014 08:11 AM
Klutzershy

Actually, now that I think about it, your ideas about duck typing are in fact very applicable to the ECS design. If you think about it, the components-as-data and systems-as-behaviour model is very much like duck typing - the function (system) can operate on any object (entity) as long as it has the right members (components).

ECS is just a slightly more rigid implementation of duck typing in statically-typed languages that allows for a lot of performance for the flexibility you get.

April 04, 2014 08:42 PM
Norman Barrows

I am also glad to see an article that is questioning entity component systems. I am curious why people say it is entity-component vs OOP since and entity component system is a design pattern that uses OOP.

I am not 100% certain about all of the critiques but my take away from the article is don't waste your time trying to build a system like everyone else uses. Build a system that gets the job done. Whether it is 'OOP' or ECS, build what you need to finish your game.

technically, OOP is not required for implementation of a C-E system.

April 07, 2014 02:34 AM
Kwizatz

My gripes with ECS have to do specifically with the lack of solid documentation, all the documents and blog posts I've read so far are too abstract and some leave important concepts just mentioned as if they were obvious to everyone. It would be nice to have an Article-Tutorial going over the concepts with actual code intertwined. I have started coding a proof of concept "ECS Framework" over at github, so perhaps I may take that endeavor myself in the future.

One thing that I realized is flimsy about ECS is the idea of less cache misses due to keeping components contiguously in memory, as phil_t mentioned, this IMO is only valid if you have one system one component, and systems are the ones managing their components use of memory, but it doesn't take too long to realize that both the rendering system as well as the physics system will require access to the position component, so who is the owner of the component? the physics system may require access to other components such as a velocity component for example, so you'll be referencing at least 2 different arrays of components for one system. The naive approach of keeping position on multiple components, say a rendering component and a physics component just complicates things as now you have to keep all of them in sync, loosing one of ECS features, independence between systems.

This, I think requires more though, I could see how interleaved component arrays (keeping heterogeneous components for a single entity together) could avoid cache misses, but then you'll have to iterate systems over entities rather than components over systems... which I don't really think is such a bad idea, unless you do want to go with the original concept of an entity being no class or struct at all but rather just a primary key in a SQL Select statement.

April 07, 2014 06:43 PM
rioki

I am also glad to see an article that is questioning entity component systems. I am curious why people say it is entity-component vs OOP since and entity component system is a design pattern that uses OOP.

I am not 100% certain about all of the critiques but my take away from the article is don't waste your time trying to build a system like everyone else uses. Build a system that gets the job done. Whether it is 'OOP' or ECS, build what you need to finish your game.

technically, OOP is not required for implementation of a C-E system.

That is true, but it helps.

April 08, 2014 07:27 AM
jnurminen

My gripes with ECS have to do specifically with the lack of solid documentation, all the documents and blog posts I've read so far are too abstract and some leave important concepts just mentioned as if they were obvious to everyone. It would be nice to have an Article-Tutorial going over the concepts with actual code intertwined. I have started coding a proof of concept "ECS Framework" over at github, so perhaps I may take that endeavor myself in the future.

One thing that I realized is flimsy about ECS is the idea of less cache misses due to keeping components contiguously in memory, as phil_t mentioned, this IMO is only valid if you have one system one component, and systems are the ones managing their components use of memory, but it doesn't take too long to realize that both the rendering system as well as the physics system will require access to the position component, so who is the owner of the component? the physics system may require access to other components such as a velocity component for example, so you'll be referencing at least 2 different arrays of components for one system. The naive approach of keeping position on multiple components, say a rendering component and a physics component just complicates things as now you have to keep all of them in sync, loosing one of ECS features, independence between systems.

This, I think requires more though, I could see how interleaved component arrays (keeping heterogeneous components for a single entity together) could avoid cache misses, but then you'll have to iterate systems over entities rather than components over systems... which I don't really think is such a bad idea, unless you do want to go with the original concept of an entity being no class or struct at all but rather just a primary key in a SQL Select statement.

1.) Lack of solid documentation is mainly because it is a pattern, idea abstracted away from its original use-case. But keep in mind that ECS can by used to solve several problems in game / game engines. It maybe a solution to a question "How designers can create new entities without help of programmers? / How to let designers easily to modify different properties/attributes of certain entities?" or it might be a solution for problem "How to create re-usable game logic and avoid OOP inheritance problems?".

First question is more visible in Unity 3D, it exposes entity construction to designers with simple UI. You can easily create new types of entities just by adding few components. With build-in components you can get far, but gets more complex when you want to create custom components.

If you create such solution by yourself you need to pay attention how you can easily create new components with editor. One solution might be defining a metadata to describe component attributes (keys, names, descriptions, types, mix & max values, default values etc.) or you can go with fully DB backed up solution. Once this is "solved" you need to figure out that do you want to simulate game inside your editor, if yes, you need to figure out how you can make editor to run that custom system that you just created. You could easily compile new engine (dynamic lib) for editor, or you could decide that editor is just a DB/entity browser and it will communicate with your game binary via TCP/IP. You might also get a request to create prefab system to aid level designers and ton of other things...

Second question is different beast. First question was more of how to create and pass data to engine's subsystems and it normally follows subsystems' features. But in logic / behaviour component side it is all about logic and of course ton of variables to fine tune game play. Some prefer doing this with scripting language so you have ScriptComponent or similar in our engine side and this component is exposed via editor UI. ScriptComponent points to some external script assets which has the actual logic, and usually has some extra attributes for engine. In side this script asset you then have your logic, and depending you choices you can have another ECS system implemented with script language and dedicated to make logic scripting more easy. If are planning to go without scripting language then ECS behaviour system is more vital to you, it helps you to create logic with languages like C++. It is also more vital since you most probably want to expose all possible variables to editor UI to make those accessible by designers. Depending what you are doing you will most likely need a message/event system between different system, system are depending on each other more heavily etc. But this is game implementation side of things, so it can be messy and it certainly will, but having ECS in place you will have some changes to create re-usable logic components and debugging should be more easier.

2.) I would say that it isn't naive approach to duplicate e.g. position, orientation and scale for rendering and physics components. Those are two different "world", so it is pretty much how it should go anyway. What you really need is a message/event "system" that can be used to sync data between different components. It can be something sophisticated or you can design our engine's update loop in a way that you can pass updated cache friendly continuous data blocks from system to system. Duplication also helps you to make your system concurrent, each task/job can run pretty much parallel without any problems if you keep dependencies between system low.

April 08, 2014 04:40 PM
BrokenKingpin

I am also glad to see an article that is questioning entity component systems. I am curious why people say it is entity-component vs OOP since and entity component system is a design pattern that uses OOP.

I am not 100% certain about all of the critiques but my take away from the article is don't waste your time trying to build a system like everyone else uses. Build a system that gets the job done. Whether it is 'OOP' or ECS, build what you need to finish your game.

technically, OOP is not required for implementation of a C-E system.

That is true, but it helps.

I think the argument was more against deep inheritance trees, not OOP entirety. It is probably still a good idea to implement you C-E system with objects, but you are avoiding deep inheritance in favour of aggregation.

As other people have said, do whatever works best for your game. For me, the entity systems reduces the complexity and dependencies the entities have on each other.

April 08, 2014 06:54 PM
Kwizatz
[quote name="jnurminen" timestamp="1396975255"] 1.) Lack of solid documentation is mainly because it is a pattern, idea abstracted away from its original use-case. But keep in mind that ECS can by used to solve several problems in game / game engines. It maybe a solution to a question "How designers can create new entities without help of programmers? / How to let designers easily to modify different properties/attributes of certain entities?" or it might be a solution for problem "How to create re-usable game logic and avoid OOP inheritance problems?". First question is more visible in Unity 3D, it exposes entity construction to designers with simple UI. You can easily create new types of entities just by adding few components. With build-in components you can get far, but gets more complex when you want to create custom components. If you create such solution by yourself you need to pay attention how you can easily create new components with editor. One solution might be defining a metadata to describe component attributes (keys, names, descriptions, types, mix & max values, default values etc.) or you can go with fully DB backed up solution. Once this is "solved" you need to figure out that do you want to simulate game inside your editor, if yes, you need to figure out how you can make editor to run that custom system that you just created. You could easily compile new engine (dynamic lib) for editor, or you could decide that editor is just a DB/entity browser and it will communicate with your game binary via TCP/IP. You might also get a request to create prefab system to aid level designers and ton of other things... Second question is different beast. First question was more of how to create and pass data to engine's subsystems and it normally follows subsystems' features. But in logic / behaviour component side it is all about logic and of course ton of variables to fine tune game play. Some prefer doing this with scripting language so you have ScriptComponent or similar in our engine side and this component is exposed via editor UI. ScriptComponent points to some external script assets which has the actual logic, and usually has some extra attributes for engine. In side this script asset you then have your logic, and depending you choices you can have another ECS system implemented with script language and dedicated to make logic scripting more easy. If are planning to go without scripting language then ECS behaviour system is more vital to you, it helps you to create logic with languages like C++. It is also more vital since you most probably want to expose all possible variables to editor UI to make those accessible by designers. Depending what you are doing you will most likely need a message/event system between different system, system are depending on each other more heavily etc. But this is game implementation side of things, so it can be messy and it certainly will, but having ECS in place you will have some changes to create re-usable logic components and debugging should be more easier. 2.) I would say that it isn't naive approach to duplicate e.g. position, orientation and scale for rendering and physics components. Those are two different "world", so it is pretty much how it should go anyway. What you really need is a message/event "system" that can be used to sync data between different components. It can be something sophisticated or you can design our engine's update loop in a way that you can pass updated cache friendly continuous data blocks from system to system. Duplication also helps you to make your system concurrent, each task/job can run pretty much parallel without any problems if you keep dependencies between system low.[/quote] 1. I would say it is closer to a paradigm than a pattern, you can usually describe a pattern with a class diagram solidifying the abstract idea, with ECS, you have to mix and match concepts depending on your needs/tastes, I don't disagree with you, I just feel that what you mentioned is a sign of the idea's novelty, as it matures, a more specific approach should surface. 2. I feel that if you have to keep data in sync between 2 different components/systems, you are in part defeating the purpose of keeping systems separated and independent from one another, might as well go back to the old ways, it would be less complicated. Also I don't see how rendering position and physics position belong to different worlds, OK, physics position may be the center of gravity, while rendering position may be the mesh origin, if you keep the physics position as an offset from the rendering position, or the other way around you don't have to sync them at all.
April 09, 2014 05:54 AM
thewayout_is_through

First, I have to say when people say they don't like/support OOP yet they use an Entity-Component model I have to roll my eyes.

The Entity-Component model concept is an application of GoF software architecture patterns, rather than something used in place of OOP really.

OOP gets a bad rep from reckless and lazy design practices we've all seen; mixing of core behavior or interfaces with concrete implementations, confusing options with operands, failure to understand the problem domain, etc.

The Entity-Component model you can say is built from the Iterator, Composite, Decorator, Command & Strategy patterns in the classic GoF OOP patterns.

The terms 'Entity' and 'Component' themselves are still very broad in terms of implementations; sharing some basic features in common, yet different approaches around a general assemblage of patterns.

There's probably as many variations in expression of the model as there are development teams applying such a model. None of the perfect, of that we can probably be sure.

Also a MVC pattern is not necessarily mutually exclusive to such an approach; Model (Data/Domain Model), View (Representation) and Controller (Behavior) really being about separation of concerns into bounded logical contexts vs. concrete implementation.

In the end we really just create abstractions that help to make the whole thing managable and deliver on our needs. So ideally we mix the best-of-breed approaches to suit the individual challenges those needs create in a way we can cope with.

April 10, 2014 03:37 AM
Truerror

Just an addition: You used Python as an exampe of weakly typed language. While I agree that it is not the strongest typed language out there, it's arguably still a strongly typed language, albeit a dynamic one. For example, it will not let you add a string to an int.

April 10, 2014 07:42 AM
swiftcoder

One thing that I realized is flimsy about ECS is the idea of less cache misses due to keeping components contiguously in memory, as phil_t mentioned, this IMO is only valid if you have one system one component, and systems are the ones managing their components use of memory, but it doesn't take too long to realize that both the rendering system as well as the physics system will require access to the position component, so who is the owner of the component? the physics system may require access to other components such as a velocity component for example, so you'll be referencing at least 2 different arrays of components for one system. The naive approach of keeping position on multiple components, say a rendering component and a physics component just complicates things as now you have to keep all of them in sync, loosing one of ECS features, independence between systems.

I think you are massively overstating this problem.

Are your components really so light on data that you can fit multiple different components in a single cache line? A single 4x4 float matrix takes up an entire cache line on most systems, so I strongly doubt it.

Realistically, you want to go even further with the 'outboard' nature of the ECS design if you want to solve cache coherency issues. Establish a single, stand-alone array of position data, which is traversed by both the physics and render systems in turn.
April 11, 2014 01:50 PM
thewayout_is_through

One thing that I realized is flimsy about ECS is the idea of less cache misses due to keeping components contiguously in memory, as phil_t mentioned, this IMO is only valid if you have one system one component, and systems are the ones managing their components use of memory, but it doesn't take too long to realize that both the rendering system as well as the physics system will require access to the position component, so who is the owner of the component? the physics system may require access to other components such as a velocity component for example, so you'll be referencing at least 2 different arrays of components for one system. The naive approach of keeping position on multiple components, say a rendering component and a physics component just complicates things as now you have to keep all of them in sync, loosing one of ECS features, independence between systems.

I think you are massively overstating this problem.

Are your components really so light on data that you can fit multiple different components in a single cache line? A single 4x4 float matrix takes up an entire cache line on most systems, so I strongly doubt it.

Realistically, you want to go even further with the 'outboard' nature of the ECS design if you want to solve cache coherency issues. Establish a single, stand-alone array of position data, which is traversed by both the physics and render systems in turn.

Even if you can't keep the data in a single cache line, there's still a fairly significant performance hit for having non-contiguous memory reads.

  • Thanks to eager pre-fetching on most modern hardware, a failure to align or fully utilize those cache lines will add refetching and will waste cycles.
  • Taking into account row-major ordering in most languages (C/C++, Pascal, Python, etc.) simple code may run four times slower traversing columns in an array vs. rows.

When it comes to memory management always keep these facts in mind:

  • Bandwith - The memory bus is limited, abuse limits scalablity.
  • Latency - Irregular access patterns cause cache misses, which causes stalling.
  • Locality - Unused data in caches not only waste cache, but also memory bandwidth.
  • Contention - Multi-core CPUs and threads contending over data in caches causes stalls.

Generally you'll get a noticable boost in performance out of well-aligned contiguous memory; e.g. plain-old object arrays.

Different needs and limitations faced by different sub-systems require different solutions, you blend in what works best for each challenge to get the best results.

In other words; our model the game development takes place against is just a facade that's comfortable to work with and is abstracted from the engine's underlying data and memory management details, which are all about getting the best performance out of the hardware.

April 12, 2014 02:22 AM
NEXUSKill

There is common misconception in the relationship between object orientation (OO) and entity component model (EC / ECS), the first is a language paradigm, its embedded in the programming language used and provides a thinking frame and a set of tools to work with, the latter is a design patter built WITH object orientation, EC IS object oriented.

The problem EC tries to solve, problematic deep inheritance hierarchies is a misuse of object orientation, most people are taught quite emphatically that object orientation means structuring your implementation around concrete objects and using inheritance to specialize more and more those objects and mold how they behave. This is a gross misrepresentation of what object orientation is, Inheritance is far from being the only tool in the shed of OO, Composition being another very important piece of the puzzle, and there are more, EC enforces heavy use of composition to discourage and reduce Inheritance abuse, truth is in most cases you should be using both quite a lot.

Deep inheritance is only the problem EC solves for the user of the engine, for the developer of the engine its solving an entirely different problem which is unforeseeable requirements, while there are parts of an engine that are extensively and thoroughly studied and "solved" like resource management, rendering, collision detection and so on, the more versatile you want your engine to be the more wild the possible requirements get, these requirements, what we call the Game Specific Logic, must be implemented by the user of the engine, one way of doing this is by giving the user a scripting language, which is a very powerful tool, but without an enforced structure script code bases tend to get unwieldy quite fast, enter -> EC, its a way to give the user a structure in which to organize his game logic that implicitly forces the user to do his scripting better, if you think an EC project got unwieldy, try to imagine how it would be with plain scripting.

In my experience these misconceptions come from two sources, one is language, the very name of the paradigm, Object orientation, perhaps a better name would be Concept Orientation? I'm not sure, but by language we are instinctively driven to associate Object with concrete entity like things. Another part of the problem is the way this is taught, the first thing most programmers are told is the cat hierarchy example (or some variant of it), i.e. the cat is an animal, has four legs and does both cat specific things and animal generic things.
On the surface examples like this, or the car, are good ways of illustrating the concepts of specialization, composition, aggregation, and so on, the problem is most people stick to that example like a rosetta stone and take it quite literally, missing the point completely.
The example goes to the approach of implementing a cat, when the cat is your whole problem, but you are NEVER implementing a cat, you are implementing a game, the cat is (if the game has one) only a character within the game, more often than not he is functionally indistinguishable from other characters like dogs, a crocodile or depending on the complexity of the game even a car, before you start putting names to the "objects" in your game you need to understand the level of complexity (and therefore the abstraction) your game requires.
If all these characters are so simply simulated that they all move around identically and are basically just animated sprites roaming the screen, you don't have a cat object, the cat is content, you have a free roaming agent, and it can implement all your characters with the same code.

The most important point of object orientation is abstraction, the ability of dividing and stratifying an extremely complex logic implementation of varying kinds into different levels and modules of abstraction to reduce the complexity of the problem to make it easier for people to understand and solve it. Failing to grasp this important concept is exactly how both inheritance and composition both get wildly out of control.

November 24, 2017 02:27 PM
You must log in to join the conversation.
Don't have a GameDev.net account? Sign up!

The entity component model is all the rave for the last decade. But if you look at the design it opens more issues than it solves.

Advertisement

Other Tutorials by rioki

13974 views
Advertisement