Object-oriented – Is the Entity Component System architecture object oriented by definition

architectural-patternsdesign-patternsentity-component-systemfunctional programmingobject-oriented

Is the Entity Component System architecture object oriented, by definition? It seems more procedural or functional to me. My opinion is that it doesn't prevent you from implementing it in an OO language, but it would not be idiomatic to do so in a staunchly OO way.

It seems like ECS separates data (E & C) from behavior (S). As evidence:

The idea is to have no game methods embedded in the entity.

And:

The component consists of a minimal set of data needed for a specific purpose

Systems are single purpose functions that take a set of entities which have a specific component


I think this is not object oriented because a big part of being object oriented is combining your data and behavior together. As evidence:

In contrast, the object-oriented approach encourages the programmer to place data where it is not directly accessible by the rest of the program. Instead, the data is accessed by calling specially written functions, commonly called methods, which are bundled in with the data.

ECS, on the other hand, seems to be all about separating your data from your behavior.

Best Answer

Introduction


Entity–component systems are an object-oriented architectural technique.

There is no universal consensus of what the term means, same as object-oriented programming. However, it is clear that entity–component systems are specifically intended as an architectural alternative to inheritance. Inheritance hierarchies are natural for expressing what an object is, but in certain kinds of software (such as games), you would rather express what an object does.

It is a different object model than the “classes and inheritance” one to which you’re most likely accustomed from working in C++ or Java. Entities are as expressive as classes, just like prototypes as in JavaScript or Self—all of these systems can be implemented in terms of one another.

 

Examples


Let’s say that Player is an entity with Position, Velocity, and KeyboardControlled components, which do the obvious things.

entity Player:
  Position
  Velocity
  KeyboardControlled

We know Position must be affected by Velocity, and Velocity by KeyboardControlled. The question is how we would like to model those effects.

 

Entities, Components, and Systems


Suppose that components have no references to one another; an external Physics system traverses all Velocity components and updates the Position of the corresponding entity; an Input system traverses all KeyboardControlled components and updates the Velocity.

          Player
         +--------------------+
         | Position           | \
         |                    |  Physics
       / | Velocity           | /
  Input  |                    |
       \ | KeyboardControlled |
         +--------------------+

This satisfies the criteria:

  • No game/business logic is expressed by the entity.

  • Components store data describing behaviour.

The systems are now responsible for handling events and enacting the behaviour described by the components. They are also responsible for handling interactions between entities, such as collisions.

 

Entities and Components


However, suppose that components do have references to one another. Now the entity is simply a constructor which creates some components, binds them together, and manages their lifetimes:

class Player:
  construct():
    this.p = Position()
    this.v = Velocity(this.p)
    this.c = KeyboardControlled(this.v)

The entity might now dispatch input and update events directly to its components. Velocity would respond to updates, and KeyboardControlled would respond to input. This still satisfies our criteria:

  • The entity is a “dumb” container which only forwards events to components.

  • Each component enacts its own behaviour.

Here component interactions are explicit, not imposed from outside by a system. The data describing a behaviour (what is the amount of velocity?) and the code that enacts it (what is velocity?) are coupled, but in a natural fashion. The data can be viewed as parameters to the behaviour. And some components don’t act at all—a Position is the behaviour of being in a place.

Interactions can be handled at the level of the entity (“when a Player collides with an Enemy…”) or at the level of individual components (“when an entity with Life collides with an entity with Strength…”).

 

Components


What is the reason for the entity to exist? If it is merely a constructor, then we can replace it with a function returning a set of components. If we later want to query entities by their type, we can just as well have a Tag component which lets us do just that:

function Player():
  t = Tag("Player")
  p = Position()
  v = Velocity(p)
  c = KeyboardControlled(v)
  return {t, p, v, c}
  • Entities are as dumb as can be—they’re just sets of components.

  • Components respond directly to events as before.

Interactions must now be handled by abstract queries, completely decoupling events from entity types. There are no more entity types to query—arbitrary Tag data is probably better used for debugging than game logic.

 

Conclusion


Entities are not functions, rules, actors, or dataflow combinators. They are nouns which model concrete phenomena—in other words, they are objects. It is as Wikipedia says—entity–component systems are a software architecture pattern for modeling general objects.