Is Entity Component System (ECS) considered a part of OOP or is it a completely different concept?
|
|
Short answer: Entity Component System (ECS) is not a part of OOP. The discussion that most influenced my understanding of Entity Component Systems is on T-Machine and an example framework inspired by this discussion useful for reference is Artemis. One of the fundamental concepts of OOP is encapsulation - application design breaks the domain into objects that have private state that can only be mutated via methods exposed by said object. Extending the functionality of an object can be done via inheritance or through composing existing objects into new objects that expose new accessor/mutator methods. In all cases the driving force is to create a system that is loosely coupled and thus easy to maintain and extend. A trivial game related example might be creating the notion of a GameEntity with the ability to draw itself via a public render method. This object can be extended by subclassing and the logic for rendering and all of its state is always encapsulated within. In ECS, on the other hand, application design is based on the idea that applications are fundamentally transforming/processing structured data. In such a system a GameEntity is a bundle of data against which transformations are performed - there is no encapsulation. In the Artemis framework you will notice that Entity is finalized specifically so it cannot be subclassed. Of course, not all GameEntities will have the same data - the player GameEntity may have inventory data while MOB game entities do not. If this were an RDBMS we'd have one massive sparse table that would quickly get unwieldy as the game grew. Enter components. A component is a piece of structured data that can be linked to an Entity just as one row in an RDBMS table can link to one or more rows in another table. This provides a way of structuring the methods used for transforming the data. The RenderSystem (or RenderMethod), for instance, would want to process any entity with a SpriteComponent and the InputSystem (or InputMethod) would want to process any entity with a KeyboardInputComponent. While there is a hardline position that true ECS means eschewing OOP entirely I think it is possible to incorporate OOP into ECS and still remain to true to ECS design goals. For instance, you'll notice in the Artemis framework that the systems responsible for processing entity data are objects themselves using encapsulation and inheritance. Similar functionality can be obtained without relying on inheritance or classes (I used function pointers and structs in my C version) but I don't think Artemis is any less an ECS framework, it may simply be more ripe for OO abuse. Since an ECS is based on the idea that data should drive domain design as opposed to object hierarchies it is data oriented and best understood as a concept separate from, if not mutually exclusive with, OOP. |
||||
|
|
|
A component system is just a way to organize the data belonging to your objects, and how to create processes that act on this data. It can be done with and without object oriented programming (which, really, is just a very broad term for a set of loosely related programming techniques, with a lot of dogma attached). |
|||
|
|
|
If you are referring to a Components-Based Entity System (CBES), then the answer is "it is reliant on OOP" rather than "it is a kind of OOP", since components refer to an OOP class that holds both state and functionality for that entity aspect represented by the component (whether it be physics, or AI, or a weapon slot, or a view representation). In contrast, I couldn't quite see a CBES existing in something like functional programming, where there cannot be a single "object" representing both state and functionality, since these are not bundled together in FP as they are in OOP. |
|||||||||||||||
|
|
This question seems to generate some confusion. Component based systems are not part of OOP. Originally, they don't rely on OOP functions. Component based architectures exist since long. They have been used in financial and banking apps for decades. They enable strong modularity, parallelization (even across servers) thanks to the segmented data, very simple storage mapping (database <-> component) and composition without the overhead of inheritance (and OOP). Since video games grew in complexity it became obvious that inheritance is not an efficient option when it comes to the structure of game entities. Segmenting games into systems which handle the specifics of each function simplifies the reuse and maintenance of code (across entities and across games). It also simplifies the execution of parallel tasks (i.e. run multiple systems or segments of a system in parallel). But all of this can be achieved without OOP. Here is a very primitive example of of how a component based system would look like in C:
A real implementation would allocate IDs to each component and would not rely on the array index as the entity ID. OOP languages simplify the implementation of features in entity systems, most notably the management of the components themselves, the handling of messages and other tasks shared by components... But ECS and OOP are not directly related. |
||||
|
|
|
It's definitely OOP - just advanced OOP. The classic (Gamma) Design Pattern book even documents this kind of solution, though not as an explicit pattern but under others. The section 'inheritance versus composition' explains the concept well. Somewhere the disadvantage of the 'component systems' is mentioned: systems relying heavily on object composition are difficult to learn and harder to debug. Each component encapsulates a different aspect about your game entities. The data and logic pertaining to this aspect is moved out from the entity. This is normal, not a violence of the encapsulation. The Visitor pattern also does something similar - you move out operations/methods of a class into different classes, in order to have a maintenable system. |
|||||||
|
|
I think that Entity-Component Systems lend themselves much better to data-oriented design rather than object-oriented design, as long as you're willing to use components only for storing data, in which case I would choose the term "properties" over "components". You can think of all the data that the entities hold as being in a big table. Each row of the table stores all the data for a single property for every entity. Each column of the table represents an entity as a whole.
Systems are responsible for doing operations on that data, where the same operation is performed on every entity. For example, one operation the movement system might perform would be calculating the effects of an object's acceleration and velocity.
The advantages of this design are not limited to the flexibility you get. Data-oriented programming is much friendlier in terms of cache performance, and it's easy to multithread any independent operation like in UpdateEntityMovement(), so DOD is very scalable in terms of current-gen hardware developments. More information on DOD: http://gamesfromwithin.com/data-oriented-design http://knight666.com/blog/tutorial-a-practical-example-of-data-oriented-design/ |
||||
|
|
|
Component systems are an architecutre. Object-oriented programming is the combination of object-oriented features in a programming language and the design principles behind the inclusion of these features as well as how to effectively use them. Some of the key aspects of object oriented programming are:
Some of the key aspects of component systems are:
Look at these bullet points and think about them long enough and you'll realize they can't really be classified in the same way. Object-oriented programming can be helpful in implementing a component system, but is not strictly required. And except for prototype-based languages like Lua and Javascript (where it's rarely useful to think on this kind of scale, and are often thinking of code as data), component systems are generally not baked into a language and are more of a architecture pattern. You could just as well implement a component system in idiomatic C and have it serve you as well as something similar in C++ or C# (Type-safety problems and less syntax sugar not withstanding). People interfacing with your C component system wouldn't care that it's C because they're typically just manipulating data to produce complex behavior. As for object oriented design and where it fits into this spectrum, I think that it doesn't. In my arrogant, young opinion, SOLID is essentially a list of platitudes that, while useful in a broad, rule-of-thumb kind of way, ultimately don't provide us with that much useful information beyond achieving a good sense of general organization and structure. And that's certainly not OOP-specific. Much more useful are design patterns and principles in specific languages. I just find it weird that OOP gets its own qualifier to stick in front of the word "design." When's the last time you saw a Teach Yourself Imperative Design in 24 Hours or Functional Programming Architecture for Dummies book? Having been raised on OOP, many of us generally find it easier to implement component systems in an object-oriented language because we're familiar with the design patterns and best practices of this paradigm. Haskell nerds, Lisp hackers and C gurus will have a completely different opinion on how one would approach to implementing (or possibly refusing to implement, because their languages offer superior idioms that accomplish similar goals in ways more appealing to their programming palette) this pattern. To understand the benefit and principles of component systems in game programming, try this: Imagine constantly for every second that you're building out your game's systems, that as soon as it's built you won't ever be able to actually build content for it. Another person who has no coding skill must work with it and you can only affect the outcome of their work orthogonally by updating the tools. Components are a pattern for maximimizing flexibility of creating a variety of different behaviors at runtime and enabling this behavior to be determined by non-code data. OOP can help, or it can not. |
|||
|
|
